【问题标题】:Accessing a stream inside a Nested StreamBuilder in Flutter在 Flutter 中访问嵌套 StreamBuilder 中的流
【发布时间】:2020-12-19 09:31:04
【问题描述】:

我在调用另一个 StreamBuilder 中的 StreamBuilder 时遇到问题,该 StreamBuilder 位于 RasedButton 小部件的 onPressed 字段内。基本上,我试图在内部 StreamBuilder 中访问一个流(在向其中添加数据之后),但执行不会调用这部分代码:

Widget submitButton(BuildContext ctx, AccountBloc bloc){
   return StreamBuilder(
      stream: bloc.submitValid,
      builder: (context, snapshot){
        return SizedBox(
          width: double.infinity,
          height: 60,
          child: RaisedButton(
            color: HexColor("0072b1"),
            child: Text("Sign in", style: TextStyle(
              fontWeight: FontWeight.bold,
              fontSize: 20,
              color: Colors.white
            ),
            ),
            onPressed:() {
               if(snapshot.hasData){
                 bloc.loginUser();
             
                 // DEBUGGING
                 print(bloc.isAuthenticated.listen((val) { print("debug isAuthenticated: $val"); }));
                  StreamBuilder(
                     stream: bloc.isAuthenticated,
                     builder: (ctx, snapshotA){
                       print("here");
                       if(!snapshotA.hasData){
                         return Text("loading....");
                       }
                       print("***${snapshotA.data}****");
                       if(snapshotA.data == false){
                         return navSignUpScreen(ctx);
                       }else if (snapshotA.data == false){
                         print("here");
                         return navHomeScreen(ctx);
                       }
                       return navSignUpScreen(ctx);
                     }
                 );
               }
            },
          ),
        );
      }
  );
}

BLOC部分如下:

  final _isAuthenticated = BehaviorSubject<bool>();
  Stream<bool> get isAuthenticated => _isAuthenticated.stream;

  void loginUser() async {
    var inMemory = InMemoryProvider();
    inMemory.newInMemoryProvider();

    UserModel userResult = await _repository.loginUser(_email.value, _password.value);
    if(userResult.status == 200){
      // save TOKEN
      UserModel userModel = UserModel.fromJsonToModel(userResult.data);
      bool res =  await inMemory.store(userModel.id, userModel.token);
      _isAuthenticated.sink.add(res);
    }
    _userLoginResponse.sink.add(userResult);
  }

navHomeScreen 的定义就这么简单:

class HomeScreen extends StatefulWidget {
  createState() {
    return HomeState();
  }
}


class HomeState extends State<HomeScreen> {

  int _currentIndex = 0;

  final List<Widget> _children = [
    AllReportsScreen(), UserProfileScreen()
  ];

  Widget build(context) {
    return Scaffold(
      body: _children[_currentIndex],
      bottomNavigationBar: mainBottomNavigatorBar(),
    );
  }

  Widget mainBottomNavigatorBar() {
    return BottomNavigationBar(
      type: BottomNavigationBarType.fixed,
      onTap: onTabTapped,
      currentIndex: _currentIndex,

      items: [
        BottomNavigationBarItem(
          backgroundColor: Colors.black45,
          icon: new Icon(Icons.note),
          title: new Text('Reports', style: TextStyle(fontSize: 15.0)),
        ),
        BottomNavigationBarItem(
          backgroundColor: Colors.black45,
          icon: new Icon(Icons.label_important),
          title: new Text('Attention', style: TextStyle(fontSize: 15.0)),
        ),

        BottomNavigationBarItem(
          backgroundColor: Colors.black45,
          icon: new Icon(Icons.person_pin),
          title: new Text('Profile', style: TextStyle(fontSize: 15.0)),
        ),
      ],
    );
  }


  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }

}

【问题讨论】:

  • 为什么要在 onPressed() 中返回一个小部件?它什么都不做
  • 我基本上是在回课。请问有什么更好的方法吗?此外,令人担忧的是内部 StreamBuilder 根本不运行。
  • 它绝对不会运行。您不能在 onPressed 中显示小部件。您可以做的是将 Streambuilder 放在上面的流构建器下方,并在您单击顶部的流构建器时显示底部的流构建器。
  • 谢谢@Uni。但是请你分享一个代码sn-p它是如何完成的?我的理解是,将内部 StreamBuilder 移动到 RaisedButton 正上方也不起作用,因为我刚刚尝试过。
  • 我没有关于它是如何完成的代码 sn-p 但我的建议是你有这样的东西:Column([StreamBuilder(),StreamBuilder(这个 streambuilder 将显示什么按下按钮时想要的)])

标签: flutter dart stream rxdart


【解决方案1】:

使用rxdart 中的combineLatest 将两个Streams isAuthenticatedsubmitValid 合并为一个Stream

class LoginState {
    final bool isAuthenticated;
    final bool submitValid;
}

final state$ = Rx.combineLatest(
    bloc.isAuthenticated,
    bloc.submitValid,
    (isAuth, valid) => LoginState(isAuth, valid),
);

StreamBuilder<LoginState>(
    stream: state$,
    builder: (context, snapshot) {
        final state = snapshot.data;
        if (state == null) return ...;
        if (!state.submitValid) return ...;
        if (state.isAuthenticated) return ...;
    }
)

【讨论】:

    猜你喜欢
    • 2019-12-10
    • 2018-12-04
    • 2021-02-28
    • 2020-10-25
    • 2020-05-25
    • 2020-07-14
    • 1970-01-01
    • 2020-12-19
    • 2020-12-17
    相关资源
    最近更新 更多