skip to Main Content

I think I couldnt understand the multiproviders in flutter, how it works.

I want to share two version of MyTabs class, you can see them in the following.
The problem in the second version is that the stream is being listened to only when the Third tab is selected but I do not need to do that in the first version of MyTabs class, it automatically listens to the stream without selecting the Third Tab.

import 'dart:async';

class StreamData {
  final StreamController<int> _valueStreamController = StreamController<int>();
  late Stream<int> valueStream;

  int _counter = 0;

  Stream<int> get myStream => _valueStreamController.stream;

  int get streamCount => _counter;

  StreamData() {
    valueStream = _valueStreamController.stream;
    _startTimer();
  }

  void _startTimer() {
    Timer.periodic(Duration(seconds: 1), (timer) {
      _counter++;
      _valueStreamController.add(_counter);
    });
  }

  void dispose() {
    _valueStreamController.close();
  }
}

First Version

class MyTabs extends StatelessWidget {
  MyTabs({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final Stream<int> myStream = StreamData().myStream;

    return DefaultTabController(
      length: 3,
      child: MultiProvider(
        providers: [
          StreamProvider<int>(
            create: (context) => myStream,
            initialData: 0,
          ),
        ],
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Tab Demo'),
            bottom: const TabBar(
              tabs: <Widget>[
                Tab(text: 'First'),
                Tab(text: 'Second'),
                Tab(text: 'Third'),
              ],
            ),
          ),
          body: const TabBarView(
            children: <Widget>[
              FirstScreen(),
              SecondScreen(),
              ThirdScreen(),
            ],
          ),
        ),
      ),
    );
  }
}

Second Version

class MyTabs extends StatelessWidget {
  MyTabs({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: MultiProvider(
        providers: [
          StreamProvider<int>(
            create: (context) => StreamData().myStream,
            initialData: 0,
          ),
        ],
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Tab Demo'),
            bottom: const TabBar(
              tabs: <Widget>[
                Tab(text: 'First'),
                Tab(text: 'Second'),
                Tab(text: 'Third'),
              ],
            ),
          ),
          body: const TabBarView(
            children: <Widget>[
              FirstScreen(),
              SecondScreen(),
              ThirdScreen(),
            ],
          ),
        ),
      ),
    );
  }
}

I couldnt figure out multiproviders and streams in flutter how they works.

3

Answers


  1. You can get your answer here, i have make it easy for you using AI – https://chat.openai.com/share/d103970e-8c87-4e37-b97c-3b641df79562

    Login or Signup to reply.
  2. In both versions of your code, the StreamProvider is essentially subscribed to the stream as soon as the create function is called. This doesn’t directly depend on which tab is active. The subscription behavior is more related to when the widget tree associated with each tab is built.

    The reason you might observe different behaviors between the two versions could be related to timing. If you notice the stream starting to emit values only when the "Third" tab is active, it could be due to the following reasons:

    In the second version, the stream is being instantiated within the StreamProvider’s create function. This means the stream will start emitting values as soon as there’s an active subscription to it. If the widget associated with the "Third" tab is being built later in the widget lifecycle (for instance, when the tab is selected for the first time), it might seem like the stream is only emitting when the "Third" tab is active.

    Depending on how your tabs’ widget trees are structured and when they are being built, there might be differences in when the subscription to the stream is established, giving the impression that the stream starts emitting only when a specific tab is active.

    Login or Signup to reply.
  3. It seems like you’re grappling with Flutter’s MultiProvider and streams within your code. Allow me to dissect the situation and elucidate the behavior you’re witnessing.

    StreamProvider and MultiProvider :

    StreamProvider is a class offered by the provider package in Flutter. It’s employed to expose a stream to the widget tree, enabling widgets further down in the hierarchy to listen to and respond to changes in the stream. MultiProvider, on the other hand, is utilized to amalgamate multiple providers and make them accessible to the widget tree. This grants you the capability to furnish various data elements to distinct parts of your application.

    In both variations of the MyTabs class, you’re integrating StreamProvider within a MultiProvider. In both iterations, you’re furnishing a stream of integers from the StreamData class to the widget tree. The primary disparity between the two versions lies in how the stream is generated.

    Disparity in Behavior:

    In the initial version of MyTabs, you’re generating a Stream<int> designated as myStream, and then utilizing this stream to institute a StreamProvider within the MultiProvider. Consequently, the stream is established as soon as the MyTabs widget is constructed. The stream promptly commences emitting data due to the _startTimer() method inside the StreamData class.

    Conversely, in the second iteration of MyTabs, you’re directly fabricating a StreamProvider utilizing StreamData().myStream. This signifies that the stream is shaped and initiated the moment the StreamProvider is created, which coincides with the construction of the MyTabs widget. Nevertheless, the timer within the _startTimer() method of the StreamData class doesn’t trigger instantaneously; it only kicks off when you actually choose the "Third" tab. Consequently, you’re observing a delay in data emission for the second version.

    Resolution:

    If you desire the second version to mirror the behavior of the first one, wherein the stream promptly begins emitting data, you should ensure that the timer within the _startTimer() method of the StreamData class initiates as soon as the StreamData instance is instantiated. This can be accomplished by invoking _startTimer() within the constructor of the StreamData class:

    class StreamData {
      // ... existing code ...
    
      StreamData() {
        valueStream = _valueStreamController.stream;
        _startTimer(); // Initiate the timer immediately upon instantiation of the StreamData instance
      }
    
      // ... remainder of the code ...
    }
    

    By effecting this alteration, the stream will promptly commence emitting data upon establishing the StreamProvider in the second rendition of your MyTabs class, just like in the initial version.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search