Reputation: 1164
I am using the bindStream()
function with the GetX
package inside a controller.
class FrediUserController extends GetxController {
@override
void onReady() {
super.onReady();
final userController = Get.find<FrediUserController>();
var groupIds = userController.user.groups;
groupList.bindStream(DatabaseManager().groupsStream(groupIds));
ever(groupList, everCallback);
}
}
But, when the groupIds update in the FrediUserController
(with an ever function that gets triggered, I want to RE-bind the streams. Meaning, delete the existing ones and bind again with new ids, or replace the ones that have changed.
Temporary Solution: Inside ever()
function
Get.delete<FrediGroupController>();
Get.put(FrediGroupController());
This code gets run everytime my groupIds
change from the database. But I do not want to initiate my controllers every time a small thing changes, it is bad UX.
This seems difficult, could someone guide me to the right direction? Maybe there is a completely different approach to connecting two GetX controllers?
Upvotes: 2
Views: 1023
Reputation: 179
Transform your Stream with where() (from the dart:async package): Somewhere in your controller place
bool streamPaused = false;
which you set to true whenever you do not want the stream to change the value of your Rx, and then
myRx.bindStream(stream.where((_) => !streamPaused));
i.e. don't transform the stream depending on the events, but on the external parameter that lets you pause it.
No need for editing the getx source or using rxdart. Make sure, if needed, to update the value of the Rx when you set streamPaused
from true
back to false
(here it helps if the stream is a BehaviourSubject
from rxdart, but of course there are other options).
Upvotes: 0
Reputation: 1775
I've also run into this issue, and there appears to be no exposed close function. There is a different way to do it though, using rxdart:
import 'package:get/get.dart';
import 'package:rxdart/rxdart.dart' hide Rx;
class YourController extends GetxController {
final value = 0.obs;
final _closed = false.obs;
void bindValue(Stream<int> valueStream) {
_closed
..value = true
..value = false;
final hasClosed = _closed.stream.where((c) => c).take(1);
value.bindStream(
valueStream.takeUntil(hasClosed)
);
}
}
Whenever you want to unbind, just set _closed.value = true
.
Upvotes: 0
Reputation: 9196
Note: the first one include editing the source code of the Getx package.
first: looking in the source code of the package :
void bindStream(Stream<T> stream) {
final listSubscriptions =
_subscriptions[subject] ??= <StreamSubscription>[];
listSubscriptions.add(stream.listen((va) => value = va));
}
here is what the bind stream actually do, so if we want to access the listSubscriptions
list, I would do:
final listSubscriptions;
void bindStream(Stream<T> stream) {
listSubscriptions =
_subscriptions[subject] ??= <StreamSubscription>[];
listSubscriptions.add(stream.listen((va) => value = va));
}
now from your controller you will be able to cancel the streamSubscription
stored in that list with the cancel
method like this :
listSubscriptions[hereIndexOfThatSubscription].cancel();
then you can re-register it again with another bindStream
call
second :
I believe also I've seen a method called close()
for the Rx<T>
that close the subscriptions put on it, but I don't know if it will help or not
Rx<String> text = ''.obs;
text.close();
Upvotes: 1