So I have Flutter Connectivity Stream.
var subscription = Connectivity().onConnectivityChanged;
And 2 Pages (Tabs) in which I have one StreamBuilder. For some reason, I can't use the same stream with 2 builders (for the first time it works but after I switch tab other StreamBuilder doesn't receive any data)
I tried making 2 separate Connectivity Streams it didn't work.
StreamBuilder(
stream: subscription,
builder: (BuildContext cntx,
AsyncSnapshot<ConnectivityResult> snapShot) {
if (!snapShot.hasData) return CircularProgressIndicator();
var result = snapShot.data;
switch (result) {
case ConnectivityResult.none:
CASE WITHOUT NETWORK
case ConnectivityResult.wifi
CASE WITH NETWROK
default:
}
}
)
I have 2 tabs like that for a different purpose.
From what I understand, you'd like when you subscribe to the stream to get the last value it emitted. A Stream does not emit its current value if you subscribe to it again. If that is indeed what you want to do, you need to use BehaviorSubject.
Related
i am working on flutter project Apply Getx and MVC Arcitecture but when i am getting stream from firestore first it got null values but when hot reload on that page values will goes in to place how to remove this Error, Almost in All type of modules I have to face this Error.
I am trying init State but Ui build first than function in Init State.
It is quite normal for StreamBuilders or FutureBuilders to call their builder function with null values.
The reason is that the build function may be called at any time, irrespective of the stream or future's state.
You should use the hasData property of the snapshot to check for valid data, and handle the case of null data, e.g. by returning a SizedBox widget.
StreamBuilder(
stream: yourStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return yourWidget();
} else {
return const SizedBox();
}
},
);
a Flutter beginner here so if my question is stupid don't mind it...
How can I convert a Stream to a Future?
I have a Stream that just calls the requested URL multiple times because it's a Stream. I want to be able to get the data and not the loading state... Because I always just get loading forever
Is there something like Future.fromStream() function somewhere and I'm missing it?
Can I achieve this?
I didn't provide any code because I think it's not needed if you need the code, I can edit the question
Stream has firstWhere method, this will return Future
_profileService.profileStream.firstWhere((element) => false);
Stream and Future are two different concepts.
As you are using, stream is keeping the data updated, and Future is just one time.
Example of using stream: Shopping Cart, listing of items
Example of using future: getUserDetails after login.
If you're using stream, then you can use streambuilder to build your UI
StreamBuilder<User>(
stream: userBloc.author, // your stream here
builder:
(BuildContext context, AsyncSnapshot<User> snapshot) {
if (snapshot.connectionState == ConnectionState.active && snapshot.hasData) {
// do your work here
} else {
return CircularprogressIndicator();
}
},
)
Here is snippet of code for loading data from firebase realtime database to a list:
var CategoryName = FirebaseDatabase.instance.reference().child('CategoryNames').once()
.then((DataSnapshot dataSnapshot){
var key = dataSnapshot.value.keys;
for(var i in key)
{
// print(dataSnapshot.value[i]['Name']);
CategoriesOnly categoriesOnly = new CategoriesOnly(
dataSnapshot.value[i]['Name']
);
categoriesOnlyList.add(categoriesOnly);
}
setState(() {
print(categoryItemList.length);
});
});
I'm storing these data into a list and showing them into ListView.builder.
And I want to show the screen once data is fully loaded meanwhile it show some kind of loading widget or loading screen but in my case screen looks blank and after sometime it shows the data. And if internet connectivity is slow blank screen appears for a minutes and loads it(because my data contains images as well). And also I want if loading time exceeds from some specific time it will show try reloading again or internet connectivity error. Please help.
As the other people already said I think the best solution would be a FutureBuilder like this:
FutureBuilder(
future: //your future you want the data from,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text("None");
case ConnectionState.active:
return Text("active");
case ConnectionState.waiting: /while you are waiting for the data...
return CupertinoActivityIndicator(); //thats the typical apple loading
return CircularProgressIndicator(); // this would be a blue circle
case ConnectionState.done:
//you have the data and can access it with 'snapshot.data'
}
}),
I'm currently working on an app and I want to get some data of a user's friends. Ideally, after sign in, this information is loaded up onto the screen for viewing.
I initially made my function call to do this within the "build" method of my HomeScreen, but this caused an infinite loop as the function call ended with "notifyListeners()".
That being said, where should I place my call to avoid a loop, while still having the UI update once the data has been fetched from the database?
You should have a look at the FutureBuilder widget, which provides great functionality to load async data and show the result once available. While the data is loading, or if your code runs into an error, you can show a different widget. Essentially it works like this:
FutureBuilder<String>(
future: _yourFuture,
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.active:
case ConnectionState.waiting:
// Return loading indicator
return Container();
case ConnectionState.done:
if (snapshot.hasError) {
// Return error
return Container();
} else if (snapshot.hasData) {
// Data loaded => use snapshot.data to access it
return Container();
}
}
})
I would not recommend to load data during initState(), since this method cannot be async and thus, you cannot await your result.
I hope that helps.
I create chap app now.
In some of the tutorials, when you read chat messages, you write the following code.
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('chat').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Text('Loading...');
default:
return ListView(
children: snapshot.data.documents.map((DocumentSnapshot document) {
return Text(document["message"]);
}).toList(),
);
}
}
)
In the above implementation, I think that if the number of messages is large, the number of readings will increase dramatically.
If there are 100 messages in the database, every time a message is added it will be 100 or more reads, right?
Or does the FireStore SDK handle it well?
it is my question.
Please tell me the code that reduces the number of reads.
Since you use a stream, the Firebase client keeps an active observer between the client and the server. For the first 30 minutes after starting this observer that means it'll only need to synchronize the delta, so whatever documents it doesn't have in its local cache yet.