2

I'm using a library for activity recognition in flutter which creates a stream for activity recognition data that comes from the sensors of the phone, I'm able to start stream but not able to stop it when tab from bottom navigation bar changes.

I'm following this example, so now i want to have a start & stop button which can start & stop the stream listening.

I have created it like this :

Stream<Activity> stream;
StreamController<Activity> streamController = new StreamController();

stream = ActivityRecognition.activityUpdates();
if(!streamController.hasListener){
      streamController.addStream(stream);
      streamController.stream.listen(onData);
  }

Future<void> onData(Activity activity) async {
    String formattedDate() {
      var date = DateTime.now();
      return date.day.toString() +
          "/" +
          date.month.toString() +
          "/" +
          date.year.toString() +
          "  " +
          date.hour.toString() +
          ":" +
          date.minute.toString() +
          ":" +
          date.second.toString();
    }

    insertActivity(RecognizedData(
        activity: activity.type.toString(),
        confidence: activity.confidence,
        dateTime: formattedDate()));
  }

And then in dispose & deactivate method i have written code like this:

@override
  void dispose() {
    streamController.close();
    print("STREAM_CLOSED");
    super.dispose();
  }

  @override
  void deactivate() {
    streamController.close();
    print("STREAM_CLOSED");
    super.deactivate();
  }

But it doesn't stop the streaming when the tab changes from bottom navigation bar, so when i open that tab again it shows "Bad State : Stream has already been listened to", so please help me with how to solve this.

Thanks in advance.

Karan Mehta
  • 1,442
  • 13
  • 32
  • Tabs are not pages so when you change them you are not running dispose or deactivate (I presume your print statements do not run?), I can't see if you are setting up the stream outside of initState but assume you are as it would explain the error. InitState should also not rerun when changing tabs. – GrahamD Jul 29 '20 at 06:12

1 Answers1

2

even if the one of the tabs is not visible the dispose will never be called, as the parent of the tab still exists on the route stack.

you have two options

  1. make the stream a broadcast stream
  2. below

rather than making the stream a BroadCast change the listener function when required like this


  //obtain the subscription only once, with a dummy listener if you prefer
  //stream.listen just sets the onData function
  var sub = stream.listen((event){});

  //just change the listener like this in the required tabs
  //tab A
  sub.onData((event) { });

  //tab B
  sub.onData((event) { });
Yadu
  • 2,979
  • 2
  • 12
  • 27