alibaba / fish-redux

An assembled flutter application framework.
https://github.com/alibaba/fish-redux
Apache License 2.0
7.33k stars 844 forks source link

页面需要监听 AppStore 中的 stream 时,如何监听到 stream 的改变 #397

Closed cenumi closed 5 years ago

cenumi commented 5 years ago

有一个登录行为,登录 websocket 拿到其 stream,并引发 AppState 的更新,在页面中我在 effect中的 LifeCycle.initState 中 listen 这个stream,当断网引发重连后,steam发生改变,在不重新进入这个页面的情况下,我该如何listen 这个改变后的stream, 试过 LifeCycle 中的其他相关生命周期,只有build有用,但会调用太多次导致多重监听。重新进入该页面,相当于重新执行了 initState,也是可以正常的,这样会十分影响用户体验。 (监听这个 stream 会 dispatch Action) 是否有其他解决方案。

cenumi commented 5 years ago

已知可以在 LifeCycle.initState 使用 #315 中的方法,但这样的话和将 AppStore 和 PageStore 连接起来的操作是否就有些重复的意思。

CoolBerry commented 5 years ago

或许可以用一个外部的class来更新appstate,页面里面只绑定appstate

cenumi commented 5 years ago

或许可以用一个外部的class来更新appstate,页面里面只绑定appstate

websocket onError 回调写在创建App 的构造器里面,每当触发就会 dispatch AppState 中的 action 来改变 其中的 stream。 appState 中的 stream 是正常改变了,但是在页面中接收不到这个变化(该页面连接了 AppStore),在 LifeCycle.initState 中 listen 的stream 不会随着 state 更新而更新。 需要一个回调来实现 state 中的 stream 更新后重新listen 这个新的 stream,理论上应该是 Lifecycle.didUpdateWidget ,但是实际上无效。

zjuwjf commented 5 years ago

不知道理解的对么

websocket ->
      appState.stream change -> 
             page.effect.listen(appState.stream) -> 
                    dispatch action;

确实是个比较绕的问题。

关键来看,你想要监听appState.stream的变化,来执行对后续stream事件的监听。

可以在LifeCycle.initState, 注册对AppStore的监听


void _initState(Action action, Context ctx) {
      var unsubscribe = appStore.subscribe( () {
             if(appStore.stream changes) {
                     appStore.stream.listen((data){
                             dispatch
                     })
             }
      });

    ctx.registerOnDisposed(unsubscribe);
}
zjuwjf commented 5 years ago

而不管是 AppStore和PageStore的连接,还是 #315 都是用来做数据变化驱动ui刷新的。

zjuwjf commented 5 years ago

当然你提到的,build方法是最合适的, 但是要去重(去除非stream变化带来的刷新)。

cenumi commented 5 years ago

不知道理解的对么

websocket ->
      appState.stream change -> 
             page.effect.listen(appState.stream) -> 
                    dispatch action;

确实是个比较绕的问题。

关键来看,你想要监听appState.stream的变化,来执行对后续stream事件的监听。

可以在LifeCycle.initState, 注册对AppStore的监听

void _initState(Action action, Context ctx) {
      var unsubscribe = appStore.subscribe( () {
             if(appStore.stream changes) {
                     appStore.stream.listen((data){
                             dispatch
                     })
             }
      });

    ctx.registerOnDisposed(unsubscribe);
}

十分感谢!! 目前写的就是这个解决方案。 其实还有一点疑惑就是对于全局级别的事件发生,比如App的生命周期事件,以及网络状态变化,这些应该被分配在哪里,当前我继承了 MaterialApp 并将监听写在了构造方法里面,发生变化时向全局 store 发出 action,改变 state。我觉得这样写肯定是有问题的,想求教一下。

zjuwjf commented 5 years ago

401 context.listen 这个api是会被需要的?

zjuwjf commented 5 years ago

其实还有一点疑惑就是对于全局级别的事件发生,比如App的生命周期事件,以及网络状态变化,这些应该被分配在哪里。

可以参考 https://github.com/alibaba/fish-redux/blob/master/lib/src/redux_component_mixin/widgets_binding_observer_mixin.dart

通过mixin, 可以在effect中接收到更多类型的action。

如果是标准化的需求,欢迎PR,提交规范的mixin进来。