'How to properly feed data to StreamBuilder initialData parameter?
I am using a StreamBuilder widget to display some data. When the app is recently opened, I wanted to display some initial data from my json file and feed it into the initialData optional keyword parameter of StreamBuilder.
Here is how I feed it:
MyStorage m = new MyStorage(); // Using path_provider, I accessed the json file inside this class
int x;
@override
void initState(){
super.initState();
getData();
}
getData() async{
Map<String, dynamic> myMap = await m._getMap;
x = int.parse(myMap["total"]);
}
...
@override
Widget build(BuildContext context){
...
child: StreamBuilder(
stream: mystream, // coming from my BLoC class
initialData: x,
builder: (context, snapshot){
return new Text("${snapshot.data}");
}
...
The problem is it that the Text widget inside my StreamBuilder is displaying "null".
I tried to rewrite my code to this:
MyStorage m = new MyStorage();
Future<int> getData() async{
Map<String, dynamic> myMap = await m._getMap;
return int.parse(myMap["total"]);
}
...
@override
Widget build(BuildContext context){
...
child: StreamBuilder(
stream: mystream, // coming from my BLoC class
initialData: getData(),
builder: (context, snapshot){
return new Text("${snapshot.data}");
}
...
but it displayed on my Text widget as "Instance of Future:int"
I have no problem with my stream parameter in the StreamBuilder. It displays the correct value that I'm expecting from the BLoC class.
The only problem I had is the feeding of initialData from my json file.
What am I doing wrong? I would appreciate any kind of help. Thanks
[UPDATE]
After a long hours of thinking a solution, I gave up using initialData parameter since after I added int to StreamBuilder like this StreamBuilder<int>() it prompted me that it will only take a value of integer. I couldn't fed it with a type of Future or Stream so I decided not to use it. What I did was I nested a FutureBuilder inside the StreamBuilder through ConnectionState.
Here is what my code now:
MyStorage m = new MyStorage();
Future<int> getData() async{
Map<String, dynamic> myMap = await m._getMap;
return int.parse(myMap["total"]);
}
...
@override
Widget build(BuildContext context){
...
child: StreamBuilder<int>(
stream: mystream, // coming from my BLoC class
//initialData: getData(),
builder: (context, snapshot){
swith(snapshot.connectionState){
case ConnectionState.none:
return new FutureBuilder(
future: getData(),
builder: (context, snapshot){
return new Text('${snapshot.data}');
}
);
case ConnectionState.active:
case ConnectionState.waiting:
return new FutureBuilder(
future: getData(),
builder: (context, snapshot){
return new Text('${snapshot.data}');
}
);
case ConnectionState.done:
if (snapshot.hasData){
return new Text('${snapshot.data}');
}
return new FutureBuilder(
future: getData(),
builder: (context, snapshot){
return new Text('${snapshot.data}');
}
);
}
}
...
I know that this solution is very inefficient but I couldn't think of a better solution as of now.
Solution 1:[1]
initialData is supposed to be the data to show before your actual data is available.
place 0 as initialData.
StreamBuilder has an additional parameter stream which is responsible for fetching your stream data. here you can do stream: getData().asStream,
edit:
Also make sure to specify the type of data you are expecting in your StreamBuilder. StreamBuilder<int>()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | edgar tremillo |
