Tomas Ward
Tomas Ward

Reputation: 1164

GetX Unbind Stream

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

Answers (3)

jakobleck
jakobleck

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

David
David

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

Gwhyyy
Gwhyyy

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

Related Questions