Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting current value from Stream

There is a StreamBuilder (using RxDart) which displays some date. After click on InkWell widget I need to calculate a new date on basis of old one. The code below simply explains the algo but when I run it there is nothing happens and execution stops after underlined row, i.e. I never see the value of lastCalcDate.

GUI:

child: StreamBuilder(
  stream: bloc.getDate,
  builder: (context,snapshot) {
    return InkWell(
      onTap: () => tapHandler
    );
}),

void tapHandler() async {
  var lastCalcDate = await bloc.getDate.single;
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  print(lastCalcDate);
  var newCalcDate = lastCalcDate.add(Duration(days:1));
  bloc.setDate(newCalcDate)
}

BLoC:

class Bloc {
  // BehaviourSubject is usedto be sure that last sent date will be accessible in `tapHandler`.
  final _dateSubject = BehaviourSubject<DateTime>(); 
  Observable<DateTime> get getDate => _dateSubject.stream;
  Function(DateTime) get setDate => _dateSubject.add;
}

To implement what I need I created some workaround but I don't like it because I fill that I can do the same thing using observables.

BLoC (workaround):

class Bloc {
  final _dateSubject = BehaviourSubject<DateTime>(); 
  Observable<DateTime> get getDate => _dateSubject.stream;
  DateTime _date;
  void setDateWorkaround(DateTime date) {
    _date = date;
    _dateSubject.add(date);
  }
}

Could you someone to give me advise. What I did wrong?

like image 965
BambinoUA Avatar asked Apr 18 '19 14:04

BambinoUA


1 Answers

single will not work because it is going to return the next item in the stream, however, that has to be added first. This means that single will just wait for the next item and in your case it will not happen.

Since you are using rxdart and BehaviorSubject already, you can easily access the current element like this:

class Bloc {
  final _dateSubject = BehaviourSubject<DateTime>(); 
  Observable<DateTime> get getDate => _dateSubject.stream;
  Function(DateTime) get setDate => _dateSubject.add;

  DateTime get currentDate => _dateSubject.value;
}

In this case, I am making use of BehaviorSubject.value, which is actually the whole point of that class.

Now, you can just use currentDate in your tap handler:

void tapHandler() async {
  var lastCalcDate = bloc.currentDate;
  print(lastCalcDate);
  var newCalcDate = lastCalcDate.add(Duration(days:1));
  bloc.setDate(newCalcDate)
}
like image 177
creativecreatorormaybenot Avatar answered Oct 04 '22 13:10

creativecreatorormaybenot