how to access snapshot.data inside Listview.builder inside futurebuilder - flutter

I am getting error The method '[]' can't be unconditionally invoked because the receiver can be 'null'.
Mydata inside _categoriesList future
[
{
"business_category_id": 1,
"business_category": "Manufacturer",
"business_category_image": "164423936662011a06c450d.png"
},
{
"business_category_id": 2,
"business_category": "Distributor",
"business_category_image": "164423937762011a11033aa.png"
},
{
"business_category_id": 3,
"business_category": "Wholesaler",
"business_category_image": "164423938762011a1bb2e3c.png"
},
{
"business_category_id": 4,
"business_category": "Retailer",
"business_category_image": "164423940062011a28189e5.png"
},
{
"business_category_id": 5,
"business_category": "Reseller",
"business_category_image": "164423941362011a3554148.png"
},
{
"business_category_id": 6,
"business_category": "Service Provider",
"business_category_image": "164423942462011a4096996.png"
}
]
my code inside futurebuilder. I am having problem accessing snapshot.data[index]
FutureBuilder(
future: _categoriesList,
builder: (_, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: 6,
itemBuilder: (_, index) {
return Text(snapshot.data[index]); // error The method '[]' can't be unconditionally invoked because the receiver can be 'null'
});
}
},
)

Here is the example for ListView.builder:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future <List<Data>> fetchData() async {
final response =
await http.get('https://jsonplaceholder.typicode.com/albums');
if (response.statusCode == 200) {
List jsonResponse = json.decode(response.body);
return jsonResponse.map((data) => new Data.fromJson(data)).toList();
} else {
throw Exception('Unexpected error occured!');
}
}
class Data {
final int userId;
final int id;
final String title;
Data({this.userId, this.id, this.title});
factory Data.fromJson(Map<String, dynamic> json) {
return Data(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future <List<Data>> futureData;
#override
void initState() {
super.initState();
futureData = fetchData();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter API and ListView Example',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter ListView'),
),
body: Center(
child: FutureBuilder <List<Data>>(
future: futureData,
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Data> data = snapshot.data;
return
ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 75,
color: Colors.white,
child: Center(child: Text(data[index].title),
),);
}
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default show a loading spinner.
return CircularProgressIndicator();
},
),
),
),
);
}
}

Specify your data-type for list in FutureBuilder first.
FutureBuilder<List<String>>()
//
Check if you are getting data. print the data using snapshot.data.
FutureBuilder<List<String>>(
future: _categoriesList,
builder: (_, snapshot) {
if (snapshot.hasData) {
print("snapshot:: data >>>> ${snapshot.data}");
return ListView.builder(
itemCount: 6,
itemBuilder: (_, index) {
return Text(snapshot.data[index]); // error The method '[]' can't be unconditionally invoked because the receiver can be 'null'
});
}
},
)

Assuming you have a Category class, with variables for the CategoryId,CategoryName,CategoryImage with all the needed methods as shown in https://stackoverflow.com/a/71029334/12371668
//create an instance of the category class before the build() method
final category = Category();
#override
Widget build(BuildContext context) {
// other code
FutureBuilder(
future: category.fetchData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Category> categories = snapshot.data();
return ListView.builder(
itemCount: categories.length,
itemBuilder: (context, index) {
var category = categories[index];
return Text(category.CategoryName);
});
}
},
)
}

Related

how can i get length of list in widget

I can't get the length of the list in the widget although I wrote everything correct
this is my cubit
class AppCubit extends Cubit<NewsStates> {
AppCubit() : super(NewsInit());
static AppCubit get(context) => BlocProvider.of(context);
MianTeams? mianTeams;
void getTimes() {
emit(NewsLoding());
DioHelper.getData(
Query: {"action": "get_teams", "league_id": "141", "APIkey": api})
.then((value) {
mianTeams = MianTeams.fromJson(value.data);
////////////////+++++ i can get the length here in cubit
print(mianTeams!.team.length);
emit(NewsSucsess());
}).catchError((onError) {
print(onError.toString());
emit(NewsErorr(onError.toString()));
});
}
this is my model
class MianTeams {
List<TeamsModel> team = [];
MianTeams.fromJson(List<dynamic> json) {
json.forEach((e) {
team.add(TeamsModel.fromJson(e));
});
}
}
class TeamsModel {
String? teamKey;
String? teamName;
String? teamBadge;
List<Players> players = [];
TeamsModel.fromJson(Map<String, dynamic> json) {
teamKey = json['team_key'];
teamName = json['team_name'];
teamBadge = json['team_badge'];
json['players'].forEach((e) {
players.add(Players.fromJson(e));
});
}
}
but in Widget I can't get the length to set the itemCount of List View separated
this is my statelessWidget
class Teams extends StatelessWidget {
const Teams({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocConsumer<AppCubit, NewsStates>(
listener: (context, state) {},
builder: (context, state) {
// print(AppCubit.get(context).mianTeams!.team.length);
return Scaffold(
appBar: AppBar(),
body: ListView.separated(
itemBuilder: (context, index) => Divider(),
separatorBuilder: (context, index) => Divider(),
itemCount: AppCubit.get(context).mianTeams!.team.length),
);
});
}
}
I don't know what's wrong and I think I wrote everything correctly
The problem is that mianTeams is null until after getTimes() is called and the response is received from your API. So when the ListView tries to build initially, it's trying to get the length of a null list.
Instead of storing mianTeams directly as a property of the Cubit, you should make it a property of one of your State classes. Probably NewsSuccess - then the list will always be available in that state. And if the Cubit is in a different state, you can display a loading indicator or something.
Your Cubit might then look something like this:
class AppCubit extends Cubit<NewsStates> {
AppCubit() : super(NewsInit());
static AppCubit get(context) => BlocProvider.of(context);
void getTimes() {
emit(NewsLoding());
DioHelper.getData(
Query: {"action": "get_teams", "league_id": "141", "APIkey": api})
.then((value) {
final mianTeams = MianTeams.fromJson(value.data);
emit(NewsSucsess(mianTeams: mianTeams));
}).catchError((onError) {
print(onError.toString());
emit(NewsErorr(onError.toString()));
});
}
}
And your widget might be something like:
class Teams extends StatelessWidget {
const Teams({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocConsumer<AppCubit, NewsStates>(
listener: (context, state) {},
builder: (context, state) {
return Scaffold(
appBar: AppBar(),
body: _buildBody(state),
});
}
Widget _buildBody(NewsStates state) {
if (state is NewsError) {
// For example
return Text("Error: ${state.message}");
} else if (state is NewsLoding) {
// For example
return const CircularProgressIndicator();
} else if (state is NewsSuccess) {
return ListView.separated(
itemBuilder: (context, index) => Divider(),
separatorBuilder: (context, index) => Divider(),
itemCount: state.mianTeams.team.length),
);
} else {
// Handle any other possible states you have
}
}
}
You can use the state from builder
itemCount: state.mianTeams?.team.length,

Retrieving Firestore data in ListView but Failing

Currently struggling to make a ListView data retrieved from Firestore.
I am trying to get "kids name" saved under in the firestore as linked photo.
Firestore
No error message is shown up but the data is not retrieved correctly and shown blank screen...hope anyone can correct my code!
and here is my code:
class kidsNamePick extends StatefulWidget {
#override
_kidsNamePickState createState() => _kidsNamePickState();
}
class _kidsNamePickState extends State<kidsNamePick> {
List<Memo> kidsnamelist = [];
Future<void>fetchMemo()async{
final kidsnames = await FirebaseFirestore.instance.collection('useraccount').doc(FirebaseAuth.instance.currentUser!.uid)
.collection('kidsname').get();
final docs = kidsnames.docs;for (var doc in docs){
Memo fetchMemo = Memo(kidsname: doc.data()['kids name'],
);
kidsnamelist.add(fetchMemo);}
setState(() {
});}
#override
void initState(){
super.initState();
fetchMemo();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add/Select Kids'),
),
body: ListView.builder(
itemCount: kidsnamelist.length,
itemBuilder: (context, index){
return ListTile(
title: Text(kidsnamelist[index].kidsname),
);
},
)
);
}
}
The best way to call future method is using FutureBuilder, first change your fetchMemo to this:
Future<List<Memo>> fetchMemo() async {
try {
final kidsnames = await FirebaseFirestore.instance
.collection('useraccount')
.doc(FirebaseAuth.instance.currentUser!.uid)
.collection('kidsname')
.get();
final docs = kidsnames.docs;
return docs
.map((doc) => Memo(
kidsname: doc.data()['kids name'],
))
.toList();
} catch (e) {
return [];
}
}
then change your build method to this:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add/Select Kids'),
),
body: FutureBuilder<List<Memo>>(
future: fetchMemo(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text('Loading....');
default:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
List<Memo> data = snapshot.data ?? [];
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(data[index].kidsname),
);
},
);
}
}
},
),
);
}

How can I fetch images from api into card widget in flutter?

I'm trying to fetch api images into the card widgets in flutter. I have services, model and photos_page class. I tried lot's of ways but still doesn't work.
final photoItem = snapshot.data[index].previewURL;
I think problem is that snapshot can't get data
that's my photos_page:
import 'dart:convert';
import 'package:abcde/services/photos_model.dart';
import 'package:abcde/services/photos_service.dart';
import 'package:abcde/widgets/card_widget.dart';
import 'package:flutter/material.dart';
class PhotosPage extends StatefulWidget {
PhotosPage({Key? key}) : super(key: key);
static const String pathId = 'Photos page';
#override
State<PhotosPage> createState() => _PhotosPageState();
}
class _PhotosPageState extends State<PhotosPage> {
PhotosService photosService = PhotosService();
#override
void initState() {
// TODO: implement initState
super.initState();
photosService.getPhotos();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Photos'),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(children: [
_getProductTypeList(),
]),
),
);
}
Widget _buildListItem(
BuildContext context, AsyncSnapshot<dynamic> snapshot, int index) {
final photoItem = snapshot.data[index].previewURL;
print('photoItem is $photoItem');
return photoCard(photoItem);
}
Widget _buildList(BuildContext context, AsyncSnapshot<dynamic> snapshot) {
var values = snapshot.data;
return ListView.builder(
// itemCount: snapshot.length,
itemBuilder: (context, index) {
return _buildListItem(context, snapshot, index);
},
);
/* return ListView(
children: snapshot!.map((data) => _buildListItem(context, data)).toList(),
);*/
}
//PhotosModel photosModel = PhotosModel();
Widget _getProductTypeList() {
return Expanded(
child: FutureBuilder(
future: photosService.getPhotos(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: LinearProgressIndicator(),
);
}
return _buildList(context, snapshot);
},
),
);
}
}
that's my model class:
class PhotosModel {
String previewURL;
PhotosModel({required this.previewURL});
/* factory PhotosModel.fromJson(Map<dynamic, dynamic> json) => PhotosModel(
previewURL: json['previewURL'] as String,
);
Map<String, dynamic> toJson() {
return <String, dynamic>{'previewURL': previewURL};
}*/
/* #override
String toString() {
return 'PhotosModel{url: $previewURL}';
}*/
/*factory PhotosModel.fromJson(Map<String, dynamic> json) {
return PhotosModel(url: json['url'] as String);
}*/
factory PhotosModel.fromJson(Map<dynamic, dynamic> json) =>
_commentFromJson(json);
Map<dynamic, dynamic> toJson() => photosModelToJson(this);
}
PhotosModel _commentFromJson(Map<dynamic, dynamic> json) {
return PhotosModel(
previewURL: json['previewURL'],
);
}
Map<dynamic, dynamic> photosModelToJson(PhotosModel instance) => <dynamic, dynamic>{
'previewURL': instance.previewURL,
};
and that's my service class. I make a list getPhotos() method but doesn't work anyway.
import 'dart:convert';
import 'package:abcde/services/photos_model.dart';
import 'package:http/http.dart';
const MY_API_KEY = '26711456-bde74f403cb42e77029bc1678';
const appUrl = 'https://pixabay.com/api/';
class PhotosService {
Future getData(String url) async {
print('Calling url: $url');
final response = await get(Uri.parse(url));
if (response.statusCode == 200) {
return response.body;
} else {
print(response.statusCode);
}
}
List<PhotosModel> dataList = [];
Future<List<PhotosModel>> getPhotos({String? query}) async {
final photosData = await getData(
'$appUrl?&key=$MY_API_KEY&q=$query');
var data =json.decode(photosData);
data.forEach((element) {
dataList.add(PhotosModel.fromJson(element));
});
print('this is photos data: $photosData');
return dataList;
}
}
that's the error it shows me
The following NoSuchMethodError was thrown building:
The method '[]' was called on null.
Receiver: null
Tried calling:
and that's my card widget
import 'package:flutter/material.dart';
Widget photoCard(String url) {
return Card(
child: Image(
image: NetworkImage(url),
),
);
}
for api I use this web-page:
https://pixabay.com/api/docs/#api_search_images
thank you very much in advance
Working Example
main.dart
===============
import 'package:demo_app/photo_page.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const PhotosPage(),
);
}
}
==============
photo_service.dart
====================
import 'dart:convert';
import 'package:http/http.dart';
const apiKey = '26711456-bde74f403cb42e77029bc1678';
const appUrl = 'https://pixabay.com/api/';
class PhotosService {
Future getData(String url) async {
print('Calling url: $url');
final response = await get(Uri.parse(url));
if (response.statusCode == 200) {
return response.body;
} else {
print(response.statusCode);
}
}
List<PhotosModel> dataList = [];
Future<List<PhotosModel>> getPhotos(String query) async {
final photosData = await getData('$appUrl?key=$apiKey&q=$query');
var data = json.decode(photosData);
var items = data["hits"];
items.forEach((element) {
dataList.add(PhotosModel.fromJson(element));
});
print('this is photos data: $photosData');
return dataList;
}
}
class PhotosModel {
String previewURL;
PhotosModel({required this.previewURL});
factory PhotosModel.fromJson(Map<dynamic, dynamic> json) =>
_commentFromJson(json);
Map<dynamic, dynamic> toJson() => photosModelToJson(this);
}
PhotosModel _commentFromJson(Map<dynamic, dynamic> json) {
return PhotosModel(
previewURL: json['previewURL'],
);
}
Map<dynamic, dynamic> photosModelToJson(PhotosModel instance) =>
<dynamic, dynamic>{
'previewURL': instance.previewURL,
};
=========================
photo_page.dart
=============
import 'package:demo_app/photo_service.dart';
import 'package:flutter/material.dart';
class PhotosPage extends StatefulWidget {
const PhotosPage({Key? key}) : super(key: key);
static const String pathId = 'Photos page';
#override
State<PhotosPage> createState() => _PhotosPageState();
}
class _PhotosPageState extends State<PhotosPage> {
PhotosService photosService = PhotosService();
#override
void initState() {
super.initState();
photosService.getPhotos("flower");
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Photos'),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(children: [
_getProductTypeList(),
]),
),
);
}
Widget _buildListItem(
BuildContext context, AsyncSnapshot<dynamic> snapshot, int index) {
final photoItem = snapshot.data[index].previewURL;
print('photoItem is $photoItem');
return photoCard(photoItem);
}
Widget _buildList(BuildContext context, AsyncSnapshot<dynamic> snapshot) {
var values = snapshot.data;
return ListView.builder(
itemCount: snapshot.hasData ? snapshot.data.length : 0,
itemBuilder: (context, index) {
return _buildListItem(context, snapshot, index);
},
);
}
Widget _getProductTypeList() {
return Expanded(
child: FutureBuilder(
future: photosService.getPhotos("flower"),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: LinearProgressIndicator(),
);
}
return _buildList(context, snapshot);
},
),
);
}
}
Widget photoCard(String url) {
return Card(
child: Image(
image: NetworkImage(url),
),
);
}

NoSuchMethodError (NoSuchMethodError: The method '[]' was called on null. Receiver: null Tried calling: [](0))

I am trying to create an application and this application gets information from the open-meteo API. I keep on encountering some errors that don't know how to fix. Would appreciate any help!!
title: Text(snapshot.data[i].longitude), //This is the line that is producing the error
import 'dart:convert';
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MaterialApp(
home: HomePage(),
debugShowCheckedModeBanner: false,
));
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Future getUserData() async {
var response = await http.get(Uri.parse( 'https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&hourly=temperature_2m'));
var jsonData = jsonDecode(response.body);
List<User> users = [];
for (var u in (jsonData)) {
User user = User(u['longitude'], u['latitude'], u['hourly'], u['time'],u['temperature']);
users.add(user);
}
print(users.length);
return users;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Rangers Tool'),
),
body: Container(
child: Card(
child: FutureBuilder(
future: getUserData(),
builder: (context, AsyncSnapshot snapshot) {
return ListView.builder(
itemCount: snapshot.data?.length,
itemBuilder: (context, i) {
return ListTile(
title: Text(snapshot.data[i].longitude),
subtitle: Text(snapshot.data[i].latitude),
);
});
}
},
))), ); } }
class User {
final String longitude, latitude, hourly, time, temperature;
User(this.longitude, this.latitude, this.hourly, this.time, this.temperature); }
}
You need to add a condition to make sure that data is there by checking the status of the snapshot before using it to build your list. Similar to this:
FutureBuilder(
future: _fetchListItems(),
builder:(context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
SnapshotError(snapshot.error),
} else {
return ListView.builder(
itemCount: snapshot.data?.length,
itemBuilder: (context, i) {
return ListTile(
title: Text(snapshot.data[i].longitude),
subtitle: Text(snapshot.data[i].latitude),
);
}
}
)

Connection state always waiting

While fetching data from database in flutter snapShot.ConnectionState is always waiting and the circular progress indicator keeps on loading.
I am not getting any errors and I am using FutureBuilder to build my widget.
Class where I build my widget
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/event_provider.dart';
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: Provider.of<EventProviders>(context).fetchAndSetEvents(),
builder: (ctx, dataSnapshot) {
if (dataSnapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return Consumer<EventProviders>(
child: Text('Not found'),
builder: (ctx, eventData, ch) {
if (eventData.events.length <= 0) {
return ch;
} else {
return ListView.builder(
itemCount: eventData.events.length,
itemBuilder: (ctx, index) {
return Container(
child: Text(eventData.events[index].eventName),
);
},
);
}
},
);
}
},
);
}
}
My future class
Future<void> fetchAndSetEvents() async {
final dataList = await DBHelper.getData('user_events');
_events = dataList
.map(
(data) => EventProvider(
eventName: data['event'],
eventDate: data['date'],
id: data['id'],
),
)
.toList();
notifyListeners();
}
}
Some help will be highly appreciated
Set listen: false
future: Provider.of<EventProviders>(context, listen: false).fetchAndSetEvents(),