قائمة إعادة تحميل Flutter مع Streams و RxDart

5

لدي سؤال واحد يتعلق بكيفية إعادة تحميل قائمة بعد استدعاء مؤشر التحديث في Flutter ، باستخدام Streams و RxDart.

إليك ما لدي ، فئة النموذج الخاصة بي:

    class HomeState {

      List<Event> result;
      final bool hasError;
      final bool isLoading;

       HomeState({
        this.result,
        this.hasError = false,
        this.isLoading = false,
      });

      factory HomeState.initial() =>
          new HomeState(result: new List<Event>());
      factory HomeState.loading() => new HomeState(isLoading: true);
      factory HomeState.error() => new HomeState(hasError: true);

    }


    class HomeBloc {

      Stream<HomeState> state;
      final EventRepository repository;

      HomeBloc(this.repository) { 
        state = new Observable.just(new HomeState.initial());
      }

      void loadEvents(){
        state = new Observable.fromFuture(repository.getEventList(1)).map<HomeState>((List<Event> list){
          return new HomeState(
              result: list,
              isLoading: false 
          );    
        }).onErrorReturn(new HomeState.error())
        .startWith(new HomeState.loading());
      }

    }

القطعة الخاصة بي:

    class HomePageRx extends StatefulWidget {
      @override
      _HomePageRxState createState() => _HomePageRxState();
    }

    class _HomePageRxState extends State<HomePageRx> {
      HomeBloc bloc;

      _HomePageRxState() {
        bloc = new HomeBloc(new EventRest());
        bloc.loadEvents();
      }

      Future<Null> _onRefresh() async {
        bloc.loadEvents();
        return null;
      }

      @override
      Widget build(BuildContext context) {
        return new StreamBuilder(
            stream: bloc.state,
            builder: (BuildContext context, AsyncSnapshot<HomeState> snapshot) {
              var state = snapshot.data;
              return new Scaffold(
                body: new RefreshIndicator(
                  onRefresh: _onRefresh,
                  child: new LayoutBuilder(builder:
                      (BuildContext context, BoxConstraints boxConstraints) {
                    if (state.isLoading) {
                      return new Center(
                        child: new CircularProgressIndicator(
                          backgroundColor: Colors.deepOrangeAccent,
                          strokeWidth: 5.0,
                        ),
                      );
                    } else {
                      if (state.result.length > 0) {
                        return new ListView.builder(
                            itemCount: snapshot.data.result.length,
                            itemBuilder: (BuildContext context, int index) {
                              return new Text(snapshot.data.result[index].title);
                            });
                      } else {
                        return new Center(
                          child: new Text("Empty data"),
                        );
                      }
                    }
                  }),
                ),
              );
            });
      }
    }

تكمن المشكلة عندما أقوم بتحديث السحب من القائمة ، لا يتم تحديث واجهة المستخدم (يسمى الخادم ، الرسوم المتحركة للمؤشر أيضًا) ، أعرف أن المشكلة تتعلق بالدفق ولكن لا أعرف كيفية حلها.

النتيجة المتوقعة: عرض CircularProgressIndicator حتى يتم تحميل البيانات

أي مساعدة؟ شكر

1 إجابة

6
افضل جواب

ليس من المفترض أن تغير مثيل state .

يجب عليك بدلاً من ذلك إرسال قيمة جديدة إلى الملاحظة. لهذا السبب StreamBuilder الذي يستمع إليه state سيتم إعلامك بقيمة جديدة.

مما يعني أنه لا يمكن أن يكون لديك فقط Observable مثيل داخليا ، مثل Observable ليس لديه أي طريقة لإضافة دفع قيم جديدة. لذلك ستحتاج إلى Subject .

هذا يغير كتلتك بشكل أساسي إلى ما يلي:

class HomeBloc {
  final Stream<HomeState> state;
  final EventRepository repository;
  final Subject<HomeState> _stateSubject;

  factory HomeBloc(EventRepository respository) {
    final subject = new BehaviorSubject(seedValue: new HomeState.initial());
    return new HomeBloc._(
        repository: respository,
        stateSubject: subject,
        state: subject.asBroadcastStream());
  }

  HomeBloc._({this.state, Subject<HomeState> stateSubject, this.repository})
      : _stateSubject = stateSubject;

  Future<void> loadEvents() async {
    _stateSubject.add(new HomeState.loading());

    try {
      final list = await repository.getEventList(1);
      _stateSubject.add(new HomeState(result: list, isLoading: false));
    } catch (err) {
      _stateSubject.addError(err);
    }
  }
}

لاحظ أيضًا كيف loadEvent استعمال addError مع استثناء. بدلا من دفع HomeState مع hasError: true .

:مؤلف

أسئلة ذات صلة

فوق
قائمة طعام