I have a StreamBuilder in order to build a Chat App, but there's an issue that it unexpectedly reloads with some events. At the time it reloads, the snapshot still got the same data in it, therefore some messages are repeatedly added to the List 'messages'.
How can I prevent the StreamBuilder from doing this repetition?
Here is my StreamBuilder code:
body: SingleChildScrollView(
reverse: true,
child: Center(
child: StreamBuilder(
stream: channel.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
addText(snapshot.data.toString(), 1); // adds to messages
}
return ListView.builder(
shrinkWrap: true,
padding: EdgeInsets.only(top: 10, bottom: 10),
physics: NeverScrollableScrollPhysics(),
itemCount: messages.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.only(
left: 14, right: 14, top: 10, bottom: 10),
child: Align(
alignment: (messages[index].messageType == 'receiver'
? Alignment.topLeft
: Alignment.topRight),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: (messages[index].messageType == 'receiver'
? Colors.grey.shade200
: Colors.blue[200]),
),
padding: EdgeInsets.all(16),
child: Text(
messages[index].messageContent,
style: TextStyle(fontSize: 15),
),
),
),
);
},
);
},
),
),
),
create a List in your state class andif(snapshot.hasData){ List = snapshot.data; }
then use the items in your list instead of your snapshot;
Related
StreamBuilder(
stream: data.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
const Center(child: CircularProgressIndicator(color: Colors.blue));
}
if (snapshot.hasData) {
return ListView.builder(
physics: const BouncingScrollPhysics(parent: BouncingScrollPhysics()),
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: snapshot.data?.docs.length,
itemBuilder: (context, index) {
final DocumentSnapshot records = snapshot.data!.docs[index];
return Padding(
padding: const EdgeInsets.only(top: 10.0, right: 10, left: 10),
child: SizedBox(
width: 188,
child: Stack(
children: [
// IMAGE 2D
Container(
height: 135,
width: 135,
decoration: const BoxDecoration(
color: Colors.transparent,
shape: BoxShape.circle,
),
child: DropShadowImage(
image: Image.network(
records["image2D"],
fit: BoxFit.fitHeight,
),
offset: Offset(10, 10),
scale: 1,
blurRadius: 12,
borderRadius: 20,
),
),
],
)),
);
},
);
}
return Container();
}),
I have a list of pictures of planets. And what I need to do is set shadows for these images. I used DropShadowImage to do this. However I have a problem, that the first element of this list seems to be under a shadow layer, the rest of the list elements are working fine.
How can I fix this.
Thanks a lot.
enter image description here
return Container(
color: Colors.white,
child: StreamBuilder<QuerySnapshot>(
stream: _statusService.getStatus(),
builder: (context, AsyncSnapshot snapshot) {
return !snapshot.hasData
? CircularProgressIndicator()
: ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot movies = snapshot.data.docs[2];
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 0,
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 0,
),
child: Text(
"${movies['description']}",
style: TextStyle(
fontSize: 10,
color: Color(0xFF737599),
),
),
),
);
});
}),
);
}
}
can someone help me i am trying to call some data from firebase but its called 3 times i didn't find any solution i am waiting for your answers
I think your data length was 3 but you only show doc2. For the length of doc 3, data is displayed 3 times.
change
itemCount: snapshot.data.docs.length,
To
itemCount: 1,
I have a simple json parser and listing the news and their categories
now I am trying to do some optimisations on ListTile because I would like to use the news Images bigger and put the news title under but ListTile provide only trailing which it is unusable for me. But I can't add any styling in whole code (new child, Row, etc gives error.) Is it possible to do that in this structure or should I make a customListTile on another page and link the current mechanism to new page?
any help would be really nice
body: Container(
padding: const EdgeInsets.all(
10.0,
),
child: FutureBuilder<Articles>(
future: _futureArticles,
builder: (BuildContext context, AsyncSnapshot<Articles> snapshot) {
if (snapshot.hasData) {
final articles = snapshot.data?.data;
return ListView.builder(
padding: const EdgeInsets.all(
10.0,
),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: articles!.length,
itemBuilder: (BuildContext context, int index) {
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: ListTile(
title: Text(
'Title: ${articles[index].title}',
),
subtitle:
Text('Category: ${articles[index].category?.name}'),
trailing: Image.network(articles[index].imageUrl!),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewsViewDetail(
id: articles[index].id!,
),
fullscreenDialog: true,
),
);
},
),
);
},
);
} else if (snapshot.hasError) {
return NewsError(
errorMessage: '${snapshot.hasError}',
);
} else {
return const NewsLoading(
text: 'Loading...',
);
}
},
),
),
);
}
}
Try below answer hope its help to you ,use GridView.builder() instead of ListView.builder()
Container(
padding: EdgeInsets.all(10),
child: GridView.builder(
itemCount: 5,//use your length here(articles!.length)
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 1),
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade200),
),
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Image.network(
'your network image here',
fit: BoxFit.fill,
),
),
SizedBox(
height: 15,
),
Text(
'Your headline here',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
],
),
);
},
),
);
your screen look like ->
I'm trying to display a list of employees in my app. Here's the code I got so far:
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 20,top: 20),
child: Container(
height: 40,
width: 120,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.12),
borderRadius: BorderRadius.circular(8)),
child: Padding(
padding: const EdgeInsets.all(10),
child: Text("Employees",
style: TextStyle(
fontSize: 22,
color: Colors.black,
fontWeight: FontWeight.w600,
)),
),
),
),
StreamBuilder(
stream: Firestore.instance.collection("Employees").snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: Text("Fetching data..."));
} else if(snapshot.connectionState == ConnectionState.done){
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data.documents[index]['name']));
},
);
} else {
return Text("hol up");
}
}),
],
);
When I run the app, it just shows 'Employees' and 'hol up' in a column. Why does the list of employees not show?
I solved the issue by simply adding shrinkWrap: true in my listview.
This should work. Also get the data from the indexed document.
ListTile(
title: Text(snapshot.data.documents[index].data['name']));
How can I show an horizontal Listview inside a Stack in Flutter?
Listview is part of a card inside another (vertical) Listview.
I can show it correctly if I give it a fixed width, but I should not, and I want it to adapt to the Card width.
I have the following code:
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
final PlatformModel platform = snapshot.data[index];
final EdgeInsets padding = index == 0
? const EdgeInsets.only(
left: 16.0,
right: 8.0,
top: 8.0,
bottom: 8.0,
)
: const EdgeInsets.only(
left: 8.0,
right: 8.0,
top: 8.0,
bottom: 8.0,
);
bloc.fetchPlatformLogo(platform.platformLogo);
String fetcher = "platforms='${platform.id}'";
bloc.fetchGames(fetcher);
return Padding(
padding: padding,
child: Card(
child: Container(
height: 250.0,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Image.network(NETWORK_URL),
_listGames(fetcher),
],
),
),
),
);
},
);
and
Widget _listGames(String fetcher) {
final bloc = BlocProvider.of<GamesBloc>(context);
return Positioned(
bottom: 5.0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
height: 200,
child: StreamBuilder(
stream: bloc.games,
builder: (context,
AsyncSnapshot<Map<String, Future<List<GameModel>>>> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return FutureBuilder(
future: snapshot.data[fetcher],
builder:
(context, AsyncSnapshot<List<GameModel>> snapshotGames) {
if (!snapshot.hasData || !snapshotGames.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
if (snapshotGames.data.length == 0) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.warning,
size: 100.0,
),
Text("Nessun gioco presente"),
],
),
);
}
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshotGames.data.length,
itemBuilder: (context, index) {
final GameModel game = snapshotGames.data[index];
final lastGame = index == snapshotGames.data.length;
bloc.fetchGameCover(game.cover);
return Padding(
padding:
lastGame ? 0.0 : const EdgeInsets.only(right: 8.0),
child: GameCard(game: game),
);
},
);
},
);
},
),
),
),
);
}
But I keep getting "Horizontal viewport was given unbounded width".
If I put, for example
child: SizedBox(
height: 200,
width: 300,
child: StreamBuilder(
It shows well, but of course it is no good.
What can I do?
Can you try with this..
ListView.builder(
shrinkWrap: true,
...