Roshan
Roshan

Reputation: 3384

How to connect future result with stream in flutter?

Im trying to get data from database and transmit that data to screen using stream. I done this using FutureBuilder that solution is working as spectated , but i need to use streambuilder Can anyone help me to find the issue. I have a method that get data from database

Future<List<CementSandAggregateView>> getAllRatios() async{
   List<CementSandAggregateView> ratioList = new List();

    var types = await ratioRepository.getAll();
    for(int i = 0 ; i < types.length ; i ++){

      CementSandAggregateView view = new CementSandAggregateView();

      String cementRatio = types[i].cement.floor() < types[i].cement ? types[i].cement.toStringAsFixed(1):types[i].cement.toStringAsFixed(0);
      String sandRatio = types[i].sand.floor() < types[i].sand ? types[i].sand.toStringAsFixed(1):types[i].sand.toStringAsFixed(0);
      String aggregateRatio = types[i].aggregate.floor() < types[i].aggregate ? types[i].aggregate.toStringAsFixed(1):types[i].aggregate.toStringAsFixed(0);

      view.ratio = "$cementRatio:$sandRatio:$aggregateRatio (${types[i].name})";
      view.id = types[i].id;
      view.name = types[i].name;
      print(view.ratio);
      ratioList.add(view);
    }

    return ratioList;
  }

and i want to send this data using stream

class CementSandAggregateMixBloC {
    BehaviorSubject<Future<List<CementSandAggregateView>>> _cSAMixController;
    BLoCProvider provider;
  CementSandAggregateMixBloC(){
    provider = new BLoCProvider();
    _cSAMixController = new BehaviorSubject<Future<List<CementSandAggregateView>>>();

    _cSAMixController.add(provider.getAllRatios());
  }

  Observable<Future<List<CementSandAggregateView>>> inputObservable() => _cSAMixController.stream;

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

in my screen i use stream using streambuilder

Widget _buildBottomNavigationBar1() {
    List<BottomNavigationBarItem> items = List();

    return StreamBuilder(
      stream: _rationBloC.inputObservable(),
      builder: (context,
          AsyncSnapshot<Future<List<CementSandAggregateView>>> snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.hasData) {
            snapshot.data.then((onValue) => {
                  onValue.forEach((mix) => {})
                });

            return BottomNavigationBar(
                items: items,
                currentIndex: _selectedRatio,
                fixedColor: Theme.of(context).buttonColor,
                onTap: _onItemTapped);
          } else {
            return new Center(
              child: new CircularProgressIndicator(),
            );
          }
        } else {
          return new Container(width: 0.0,height: 0.0,);
        }
      },
    );
  }

but data is not coming to screen

i have tried this solution but no chance !

can anyone help me to convert future result in to stream ?

Thanks.

Upvotes: 2

Views: 6073

Answers (2)

BambinoUA
BambinoUA

Reputation: 7100

I think _init() should be calld in initState() method of StatefulWidget, or use this code in initState or build method.

WidgetBinding.instance.addPostFrameCallback(() => _init());

This means call of the procedure just after 1st frame rendered, i.e. just after build.

Upvotes: 0

Marcos Boaventura
Marcos Boaventura

Reputation: 4741

A simple approach to achive this is await for the future complete and then put the data inside your stream.

In your bloc class:

void _init() async {
   List<CementSandAggregateView> data = await provider.getAllRatios();
   _cSAMixController.add(data);
}

CementSandAggregateMixBloC(){
    provider = new BLoCProvider();
    _cSAMixController = BehaviorSubject< List<CementSandAggregateView> >();
    _init();
  }

Upvotes: 3

Related Questions