Bloc Pattern隐藏和取消隐藏小部件 [英] Bloc Pattern to hide and unhide Widgets

查看:63
本文介绍了Bloc Pattern隐藏和取消隐藏小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从互联网上获取一些数据并将其显示为列表.

I am trying to fetch some data from the internet and show it int a list.

以下是我的bloc代码

class StudentsBloc {
  final _repository = Repository();
  final _students = BehaviorSubject<StudentModel>();

  final BehaviorSubject<bool> _showProgress = BehaviorSubject<bool>();
  final BehaviorSubject<bool> _showNoInternetViews = BehaviorSubject<bool>();

  Observable<StudentModel> get students => _students.stream;
  Observable<bool> get showProgress => _showProgress.stream;
  Observable<bool> get showNoInternetViews => _showNoInternetViews.stream;

  //FetchStudent from my Api
  fetchStudents(String disciplineId, String schoolId, String year_id,
      String lastIndex) async {
    final student = await _repository.fetchStudents(
        disciplineId, schoolId, year_id, lastIndex);
    _students.sink.add(student);
  }

  //Check to see if user has internet or not
  isNetworkAvailable(String disciplineId, String schoolId, String year_id,
      String lastIndex) async {
    checkInternetConnection().then((isAvailable) {
      if (isAvailable) {
        fetchStudents(disciplineId, schoolId, year_id, lastIndex);
      } else {
        _students.sink.addError(NO_NETWORK_AVAILABLE);
      }
    });
  }

  Function(bool) get changeVisibilityOfProgress => _showProgress.sink.add;
  Function(bool) get changeVisibilityOfNoInternetViews =>
      _showNoInternetViews.sink.add;

  dispose() {
    _students.close();
    _showProgress.close();
    _showNoInternetViews.close();
  }
}

以下是我隐藏统一控件的主要代码

Following is my main code to hide unide Widgets

Widget buildList(StudentsBloc bloc) {
    return StreamBuilder(
      stream: bloc.students,
      builder: (context, AsyncSnapshot<StudentModel> snapshot) {
        if (snapshot.hasError) {
          bloc.changeVisibilityOfProgress(false);
          bloc.changeVisibilityOfNoInternetViews(true);

          return StreamBuilder(
            stream: bloc.showNoInternetViews,
            builder: (context, snapshot) {
              bool showNoInternetView = snapshot.hasData ?? false;

              return Visibility(
                child: Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text("No Network Available"),
                      RaisedButton(
                        onPressed: () {
                          fetchStudents();
                        },
                        child: Text("Retry"),
                      )
                    ],
                  ),
                ),
                visible: showNoInternetView ? true : false,
              );
            },
          );
        }

        if (snapshot.hasData) {
          bloc.changeVisibilityOfProgress(false);
          bloc.changeVisibilityOfNoInternetViews(false);

          return Refresh(
            year_id: "2",
            schoolId: "1",
            lastIndex: "0",
            disciplineId: "1",
            child: ListView.builder(
              itemBuilder: (context, int index) {
                return buildTile(
                    snapshot.data.toBuilder().data.studentData[index]);
              },
              itemCount: snapshot.data.toBuilder().data.studentData.length,
            ),
          );
        }

        if (!snapshot.hasData) {
          return StreamBuilder(
            builder: (context, snapshot) {
              bool showProgressIndicator = snapshot.data ?? false;

              return Visibility(
                child: Center(
                  child: CircularProgressIndicator(),
                ),
                visible: showProgressIndicator ? true : false,
              );
            },
            stream: bloc.showProgress,
          );
        }
      },
    );
  }

Scaffoldbody中调用buildList方法

void fetchStudents() {
    bloc?.changeVisibilityOfNoInternetViews(false);
    bloc?.changeVisibilityOfProgress(true);
    bloc?.isNetworkAvailable("1", "1", "2", "0");
  }

假设打开应用程序时用户已连接互联网,然后我就能看到circularprogressindicator,然后可以看到数据列表 但假设开始时打开应用程序且用户没有互联网,那么我会显示无网络可用文本"和一个重试按钮, 现在,如果用户已连接到Internet,然后单击按钮重试,那么几秒钟后我将直接看到数据列表,而不是circularprogressindicator.我无法理解为什么NoInternetviews没有隐藏并且<在显示数据列表之前,单击重试"按钮时,将显示c7>.

Suppose the user has internet when app is opened then i am able to see circularprogressindicator and then the list of data is visible but suppose at the start when app is opened and the user does not have internet then i am showing the No Network Available Text and a button to retry, now if the user has connected to the internet and then click on button to retry i am directly seeing the list of data after few seconds instead of the circularprogressindicator.I am not able to understand why the NoInternetviews are not hiding and progressindicator is showing when retry button is clicked before showing list of data.

我的流在调用的重试按钮上没有得到更新.在StreamBuilder中是否有针对StreamBuilder的警告?

My stream is not getting updated on retry button called. Are there any caveats for StreamBuilder within StreamBuilder?

我尝试更改答案中@ivenxu提到的StreamBuilder顺序,但仍然不起作用. 以下是附加代码的链接 https://drive.google.com/file/d/15Z8jXwwOpwTB1CxDS8sHz8 view?usp = sharing https://drive.google.com/open?id=1gIXV20S1o5jYRnno_NADabuIj4w163fF

I tried changing the StreamBuilder order as mentioned by @ivenxu in the answer but it still does not work. Following are the links of attached code https://drive.google.com/file/d/15Z8jXw1OpwTB1CxDS8sHz8jKyHhLwJp7/view?usp=sharing https://drive.google.com/open?id=1gIXV20S1o5jYRnno_NADabuIj4w163fF

推荐答案

在视图层中,可以使用 Visibility()小部件并在从Internet加载数据时传递可见参数true或false. 让我们考虑一下如何从bloc更改可见变量. Visibility()的父级使用 StreamBuilder()小部件以流式传输更改数据. 对于您的情况,您需要在区块内部添加 PublishSubject 来流式传输和添加新数据,并且需要 Observable 来在小部件上流式传输这些数据.

in view layer you can use Visibility() widget and pass visible parameter true or false when load data from Internet. let's think about how to change the visible variable from bloc. The parent of Visibility() widget the StreamBuilder() to stream on changes data. for your case you need a PublishSubject inside your bloc to stream and add new data, and Observable to stream on this data on your widget.

让我们显示一个代码段代码,以帮助您实现它

let's show a snippet code to help you how you can implement it

该集团包含 PublishSubject Observable 以便流式传输和添加数据

The bloc contains PublishSubject and Observable to stream and add data

  //this Subject allows sending data, error and done events to the listener
  final PublishSubject<bool> _progressStateSubject = new PublishSubject();

  //the listener are streaming on changes
  Observable<bool> get progressStateStream => _progressStateSubject.stream;

  //to change your progress state
  void changeProgressState({bool state}) => _progressStateSubject.sink.add(state);

您可以在此处更改进度状态

Here you can change your state of your progress

void callWebService() async {
    //when you call your func to fetch your data change your state to true
    changeProgressState(state: true);
    .
    .
    .
    if(response != null){
      //when your call is done change the state to false
      changeProgressState(state: false);
    }
  }

您的进度小部件是

// Loading Widget
  Widget _buildLoadingWidget(Bloc bloc) {
    return StreamBuilder<bool>(
        stream: bloc.progressStateStream,//streaming on changes
        builder: (context, snapshot) {
          return Visibility(
            visible: snapshot.data ?? false,//calling when data changes
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text("Loading data from API...",
                      textDirection: TextDirection.ltr),
                  CircularProgressIndicator()
                ],
              ),
            ),
          );
        });
  }

这篇关于Bloc Pattern隐藏和取消隐藏小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆