Instance of model in place of data & Model has no getter length Flutter - flutter

I am developing an application in Flutter. I am facing an issue with my Future. Data from future in future builder giving error Model has no getter length also it is showing in print as Instance of TopicsModel inspite of data.
Please help.
Below is my code:
topics_model.dart
class TopicsModel {
List<Topics> topics = [];
TopicsModel();
TopicsModel.fromJson(Map<String, dynamic> jsonMap) {
try {
topics = jsonMap['topics'] != null
? parseTopicsAttributes(jsonMap['topics'])
: [];
print(jsonMap['topics']);
} catch (e) {
topics = [];
}
}
static List<Topics> parseTopicsAttributes(attributesJson) {
List list = attributesJson;
print("in list making");
List<Topics> attrList = list.map((data) => Topics.fromJson(data)).toList();
return attrList;
}
}
class Topics {
int id;
String name;
Topics.fromJson(Map<String, dynamic> json) {
print("hash problem");
print(json);
id = json["sound_id"];
name = json["title"];
}
}
Future
Future<TopicsModel> getFavTopics() async {
print("get_only_fav_topics");
print(userRepo.currentUser.value.userId.toString());
print(userRepo.currentUser.value.token);
Uri uri = Helper.getUri('get_only_fav_topics');
uri = uri.replace(queryParameters: {
'user_id': userRepo.currentUser.value.userId == null
? "0"
: userRepo.currentUser.value.userId.toString(),
"app_token": userRepo.currentUser.value.token
});
try {
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
'USER': '${GlobalConfiguration().get('api_user')}',
'KEY': '${GlobalConfiguration().get('api_key')}',
};
var response = await http.get(uri, headers: headers);
if (response.statusCode == 200) {
var jsonData = json.decode(response.body);
if (jsonData['status'] == 'success') {
print("topicssssssssssssssss");
print(jsonData);
return (json).decode(response.body)['data'];
}
}
} catch (e) {
print(e.toString());
}
}
FutureBuilder in view
child: FutureBuilder<TopicsModel>(
builder: (context, projectSnap) {
print("Projeccct");
print(projectSnap);
if (projectSnap.connectionState ==
ConnectionState.none &&
projectSnap.hasData == null) {
//print('project snapshot data is: ${projectSnap.data}');
return Container();
}
if (projectSnap.connectionState ==
ConnectionState.done &&
projectSnap.hasData) {
print("ind one");
print(projectSnap.data.toString());
return ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: projectSnap.data.length,
itemBuilder: (context, index) {
return new ChoiceChip(
pressElevation: 0.0,
selectedColor: settingRepo
.setting
.value
.buttonColor,
selected: false,
backgroundColor: Colors.white,
label: Text(projectSnap
.data[index].name));
},
);
} else {
return Container();
}
},
future: getFavTopics(),
)
Json response:
{
"status":"success",
"data":{
"topics":[
{
"fav_id":1,
"sound_id":3321,
"user_id":0,
"created_at":"2021-05-07 10":"01":25,
"title":"title 1",
"sound_name":1620381685.mp3,
"cat_id":4,
"parent_id":0,
"duration":30,
"album":"Album 1",
"artist":,
"tags":null,
"used_times":0,
"deleted":0,
"active":1,
"image":fLNu9mZDAAHNYJcdNK6YRJPvPVxmpzPidHZRhhW5.jpg
},
{
"fav_id":41,
"sound_id":3319,
"user_id":0,
"created_at":"2021-05-07 09":"58":52,
"title":"Title 2",
"sound_name":1620381532.mp3,
"cat_id":2,
"parent_id":0,
"duration":15,
"album":"Album 1",
"artist":,
"tags":null,
"used_times":0,
"deleted":0,
"active":1,
"image":54PKLMXikjx0KDCHQSL8uep42oXxzF4qtvI7VpHE.jpg
}
]
}
}

You need generic
Change this
child: FutureBuilder(
to
child: FutureBuilder<List<Topics>>(

You call your future with Asynchronously
FutureBuilder<List<Topics>>(
future: getFavTopics(),
builder: (context, AsyncSnapshot<List<Topics>> projectSnap) {
For more you can read this article When should I use a FutureBuilder?

You didn't connect the Model class with your FutureBuilder. The data will come from model so call the model class like :
FutureBuilder<Topics>()

Related

How to get data from Post Method Response on Flutter?

Hi guys I'm new to Flutter
I'm trying to fetch the data from http.post method using FutureBuilder and snapshot.data but it keeps returning CircularProgressIndicator which is means snapshot has no data.
Future postDataTransaksi() async {
try {
http.Response response = await http.post(
Uri.parse('https://ignis.rumahzakat.org/donol/listTransaksi'),
body: {
'---': '---',
'---': '---',
},
headers: {
'access-token': '---'
});
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
} else {}
} catch (e) {
print(e.toString());
}
}
This is my post method code.
FutureBuilder(
future: postDataTransaksi(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Container(child: Text(snapshot.data[0]['id']));
} else {
return const Center(child: CircularProgressIndicator());
}
})
And this is how I try to fetch the data
Change your builder to this:
if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
return Container(child: Text(snapshot.data[0]['id']));
} else {
return const Center(child: CircularProgressIndicator());
}
and also change your future to this"
Future<List> postDataTransaksi() async {
try {
http.Response response = await http.post(
Uri.parse('https://ignis.rumahzakat.org/donol/listTransaksi'),
body: {
'---': '---',
'---': '---',
},
headers: {
'access-token': '---'
});
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
return data;// <--- add this
}
return [];// <--- add this
} catch (e) {
print(e.toString());
return [];// <--- add this
}
}

Flutter: Need to load values and then make a firebase query for Futurebuilder caused RangeError (index)

I'm trying to load the geo location first. Then I use this value to start a query which events are in a certain radius from this location.
I want to display these events in a FutureBuilder.
My problem:
I have to initialize Future<List> futureEvents in the onInit state, otherwise Flutter complains. At the time he didn't have the location yet.
So I call the function again at the end.
So it happens that the error "RangeError (index): Invalid value: Valid value range is empty :1" is thrown until the method is called again after receiving the geo-location and I get the data.
Sorry for bad coding. One of my first Projects
The InitState:
class _LocationPageState extends State<LocationPage> {
String? _currentAddress;
Position? _currentPosition;
late Future<List<Events>> futureEvents;
double locationRadius = 5;
#override
void initState() {
super.initState();
_getCurrentPosition();
futureEvents = _getEvents();
}
The called functions:
Future<void> _getCurrentPosition() async {
final hasPermission = await _handleLocationPermission();
if (!hasPermission) return;
await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
.then((Position position) {
setState(() => _currentPosition = position);
_getAddressFromLatLng(_currentPosition!);
}).catchError((e) {
debugPrint(e);
});
}
Future<void> _getAddressFromLatLng(Position position) async {
await placemarkFromCoordinates(
_currentPosition!.latitude, _currentPosition!.longitude)
.then((List<Placemark> placemarks) {
Placemark place = placemarks[0];
setState(() {
_currentAddress = ' ${place.postalCode} ${place.locality} ';
});
currentPLZ = place.postalCode.toString();
futureEvents = _getEvents() as Future<List<Events>>;
}).catchError((e) {
debugPrint(e);
});
}
Future<List<Events>> _getEvents() async {
// get all PLZ in a radius
final response = await http.get(Uri.parse(
'https://www.suche-postleitzahl.org/geo-api.json?action=plz-umkreis&subaction=umkreis-osm&plz=' +
currentPLZ +
'&radius=' + locationRadius.toString()));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var jsondataPlz = jsonDecode(response.body);
List<PLZData> plzdataList = [];
for (var u in jsondataPlz) {
PLZData plzData = PLZData(u['postal_code'], u['name'], u['distance']);
plzdataList.add(plzData);
}
print(plzdataList.length);
print(plzdataList[1].name +
" Distanz:" +
plzdataList[1].distance +
" PLZ only" +
plzdataList[1].postal_code);
// get all events in the radius
List<Events> events = [];
if (plzdataList.isNotEmpty) {
for (var i = 0; plzdataList.length > i; i++) {
var singleEvent = await FirebaseFirestore.instance
.collection('Events')
.where('postCode', isEqualTo: plzdataList[i].postal_code)
.get();
if (singleEvent.docs.isNotEmpty) {
var singleEventList =singleEvent.docs.map((d) => Events.fromJson(d.data())).toList();
//add distance and regionname
for(var j = 0; singleEventList.length > j; j++){
singleEventList[j].distance = plzdataList[i].distance;
singleEventList[j].regionName = plzdataList[i].name;
}
events = events + singleEventList;
if (events[0].userID != null) {
print(events[0].userID);
print(events[i].distance);
}
}
}
}
//get userdata to the events
if (events.isEmpty) {
print("Es wurden keine Events gefunden");
} else {
for (var i = 0; events.length > i; i++) {
var userInformationSnap = await FirebaseFirestore.instance
.collection('users')
.where('__name__', isEqualTo: events[i].userID)
.get();
events[i].userInformation = userInformationSnap.docs
.map((d) => UsersForPosts.fromJson(d.data()))
.toList();
print(events[i].userInformation[0].username);
}
}
return events;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load');
}
}
The FutureBuilder
FutureBuilder<List<Events>>(
future: futureEvents,
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), //<--here
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Eventcard(
userPhoto: snapshot.data?[index].userInformation[0]
.userPhoto ?? "keine Info",
age: snapshot.data?[index].userInformation[0].age ??
"keine Info",
username: snapshot.data?[index].userInformation[0]
.username ?? "keine Info",
gender: snapshot.data?[index].userInformation[0]
.gender ?? "keine Info",
meetState: snapshot.data?[index].meetState ??
"keine Info",
postCode: snapshot.data?[index].postCode ??
"keine Info",
distance: snapshot.data?[index].distance ??
"keine Info",
regionName: snapshot.data?[index].regionName ??
"keine Info",
comment: snapshot.data?[index].comment ??
"keine Info",
headline: snapshot.data?[index].headline ??
"keine Info",
);
},
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
} else {
// By default, show a loading spinner.
return const CircularProgressIndicator();
}
},
),
Have you tried to just put the _getEvents() Future inside the FutureBuilder directly instead of using it as a late variable? I’m also confused by this format… why use a Future and a FutureBuilder? It seems like you could just create an empty list events = [] then in the initState call a new async function where you fetch the events from Firestore and use that data to update the events list through setState. Then take away the FutureBuilder and just use a ListView.builder. Just search how to create a ListView from a list, it’s very simple.

RangeError index invalid value only valid value is empty 0 see also in Flutter

I'm in a Flutter project using Getx. Every time I enter the screen that lists the records I get an error message as you can see below;
I don't know where I'm going wrong, but I'll leave the main parts of the code. I need to find where I'm going wrong.
Class Repository
Future<List<Post>> getAlbum({
bool isFavoritedPage = false,
bool isNewEdition = false,
}) async {
dio.options.headers['Cookie'] = 'ASP.NET_SessionId=${user.sessionID}';
final response = await dio.get(
isFavoritedPage ? AppConstants.apiFavoritedsPost : AppConstants.apiPosts,
queryParameters: {
'sessionId': user.sessionID,
'CodUserProfile': '${user.codUser!}',
'CodUserLogged': '${user.codUser!}',
'Page': '${page}',
'pagesize': '10',
'myPostOnly': isFavoritedPage ? 'true' : 'false',
},
);
final body = response.data['ListPosts'] as List;
return body.map((post) => Post.fromJson(post)).toList();
}
Class Controller
var lstPost = List<Post>.empty(growable: true).obs;
var page = 1;
var isDataProcessing = false.obs;
// For Pagination
ScrollController scrollController = ScrollController();
var isMoreDataAvailable = true.obs;
#override
void onInit() async {
super.onInit();
// Fetch Data
getPost(page);
//For Pagination
paginateTask();
}
void getPost(var page) {
try {
isMoreDataAvailable(false);
isDataProcessing(true);
getAlbum(page).then((resp) {
isDataProcessing(false);
lstPost.addAll(resp);
}, onError: (err) {
isDataProcessing(false);
showSnackBar("Error", err.toString(), Colors.red);
});
} catch (exception) {
isDataProcessing(false);
showSnackBar("Exception", exception.toString(), Colors.red);
}
}
showSnackBar(String title, String message, Color backgroundColor) {
Get.snackbar(title, message,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: backgroundColor,
colorText: Colors.white);
}
void paginateTask() {
scrollController.addListener(() {
if (scrollController.position.pixels ==
scrollController.position.maxScrollExtent) {
print("reached end");
page++;
getMoreTask(page);
}
});
}
void getMoreTask(var page) {
try {
getAlbum(page).then((resp) {
if (resp.length > 0) {
isMoreDataAvailable(true);
} else {
isMoreDataAvailable(false);
showSnackBar("Message", "Não existem registro", Colors.lightBlueAccent);
}
lstPost.addAll(resp);
}, onError: (err) {
isMoreDataAvailable(false);
showSnackBar("Error", err.toString(), Colors.red);
});
} catch (exception) {
isMoreDataAvailable(false);
showSnackBar("Exception", exception.toString(), Colors.red);
}
}
#override
void onClose() {
searchDrawerEC.dispose();
super.onClose();
}
Future<List<Post>> getAlbum(pagina,[bool isFavoritedPage = false]) async {
final response =
await repository.getAlbum(isFavoritedPage: isFavoritedPage);
return response;
}
Class Page
Expanded(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
if (index == controller.lstPost.length - 1 &&
controller.isMoreDataAvailable.value == true) {
return Center(child: CircularProgressIndicator());
}
return PostWidget(post: controller.lstPost[index]);
}
),
),
I'm basing myself on this github project.
https://github.com/RipplesCode/FlutterGetXTodoAppWithLaravel/tree/master/lib/app/modules/home
I don't use getx, but I see something odd in your Listview.builder. It feels as if you're abusing it a little, to also show the "no data" case, and there's also no count. I think it should have a count, so something like this:
if (lstPost.isEmpty) {
return Center(child: CircularProgressIndicator());
} else {
return ListView.builder(
itemCount: lstPost.length,
itemBuilder: (BuildContext context, int index) {
return PostWidget(...);
}
);
}

How to do stream builder to get data from bloc in flutter

I am new in BLOC and I am trying to read respond from api.. but whenever I call stream builder... my widget always stops in wait... here is my code
here is api provider file
class Provider {
final _url = '...';
Future<List<LoginRespon>> login(a, b) async {
List<LoginRespon> datalogin = [];
try {
bool trustSelfSigned = true;
HttpClient httpClient = new HttpClient()
..badCertificateCallback =
((X509Certificate cert, String host, int port) =>
trustSelfSigned);
IOClient http = new IOClient(httpClient);
final response = await http.post(_url,
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
},
body: json.encode({
"aa": a,
"bb": b,
}));
Map<String, dynamic> responseJson = json.decode(response.body);
if (responseJson["status"] == "200") {
datalogin.add(LoginRespon(
status: responseJson['status'],
data: Data(
name: responseJson['data']['name'],
position: responseJson['data']['pos'])));
return datalogin;
} else {
print("ppp");
}
} on Exception {
rethrow;
}
return datalogin;
}
}
and here is for stream builder
isClick
? StreamBuilder(
stream: bloc.login(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(snapshot.data);
return Text("success");
} else if (snapshot.hasError) {
return Text(
snapshot.error.toString());
}
return Text("wait..");
},
)
: FlatButton(
child: Text("Login"),
onPressed: () {
setState(() {
isClick = true;
});
},
),
is there a way so that I can call print(snapshot.data) inside if (snapshot.hasData)
You need to pass argument which required in method otherwise it will not successfully responce (200) and it will throw error.

How to return Future List from DataSnapshot

I want to return a Future List from Firebase Database snapshot and this is my code but I cant get it work properly:
Future<List<CocheDetailItem>> getCoches(ids) async {
List<CocheDetailItem> coches = [];
final dbRef = FirebaseDatabase.instance.reference().child('17082019');
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
dbRef.child(id).once().then((DataSnapshot snapshot) {
if (snapshot.value != null) {
Map<dynamic, dynamic> jsres = snapshot.value;
CocheDetailItem coche = CocheDetailItem.fromJson(jsres);
coches.add(coche);
}
});
print('here is i ${ids[i]} ');
}
return coches;
}
The return I get is empty Area. Can anyone help me with this, please?
Note, dbRef.child(id).once(); is a async function, so you must wait it ends to get your data. Use await keyword to do it.
Future<List<CocheDetailItem>> getCoches(ids) async {
List<CocheDetailItem> coches = [];
final dbRef = FirebaseDatabase.instance.reference().child('17082019');
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
var dataSnapshot = await dbRef.child(id).once();
if (dataSnapshot.value != null) {
Map<dynamic, dynamic> jsres = dataSnapshot.value;
CocheDetailItem coche = CocheDetailItem.fromJson(jsres);
coches.add(coche);
}
print('here is i ${ids[i]} ');
}
return coches;
}
well.. I don't use firebase but I send a request to my database with this (you have to use async and await)
Future<List<PlaceModel>> getPlaces(String ciudad, String tipo) async {
Uri request = Uri.http('domain.com', '/getPlaces/$ciudad/$tipo');
ResponseModel response = ResponseModel.fromJsonMap(json.decode((await http.get(request)).body));
List<PlaceModel> items = [];
if(response.res) {
if(response.value != null) {
for(var item in response.value) {
final place = PlaceModel.fromJsonMap(item);
items.add(place);
}
}
}
print("Places Loaded: ${items.length}");
return items;
}
I use my ResponseModel to convert the json answer in an object.
Then I show it with the future builder:
class PlacesListPage extends StatelessWidget{
final _selectedLocation, _selectedList;
PlacesListPage(this._selectedLocation, this._selectedList);
final _provider = PlaceProvider();
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8.0),
child: FutureBuilder(
future: _provider.getPlaces(_selectedLocation, _selectedList), // async request to database
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) { // check when your request is done
if(snapshot.data.length != 0) { // check if any data has been downloaded
return ListView.builder( // build a listview of any widget with snapshot data
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
// i just return containers but you can use any custom widget, it's like a forEach and use the index var
return Container(
child: Text(snapshot.data[index]),
);
},
);
} else {
// If you don't have anything in your response shows a message
return Text('No data');
}
} else {
// shows a charge indicator while the request is made
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
}