2

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?

Tomas Ward
  • 854
  • 6
  • 23

3 Answers3

1

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();
Gwhyyy
  • 7,554
  • 3
  • 8
  • 35
  • 1
    thanks for the answer. Method 2 doesn't work. And I do not want to change the package source code. There HAS to be a way to reset the bindStream() function or to change streams coming from firebase without changing Getx Package. – Tomas Ward Sep 26 '22 at 23:19
  • 1
    Looking at the package source code right now regarding method 2 and this logically should work because it is iterating over the _subscriptions and cancelling them. Don't forget to bind the stream again. I would pull the bindstream in a separate function and calling it each time you want to rebind. In that function, close the rx variable before binding it. Call it each time you want to rebind. The object's stream itself also gets closed though, so you might want to reinitiating like this: rx.subject = GetStream(). – chaser Nov 07 '22 at 22:21
0

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.

David
  • 1,636
  • 19
  • 27
0

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).

jakobleck
  • 43
  • 8