alibaba / fish-redux

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

在TabbarView嵌套Component,导致Component生命周期存在异常 #541

Closed jing-pei closed 4 years ago

jing-pei commented 4 years ago

异常情况 当我在TabbarView的每个Tab页面嵌套一个Component时(4个),如果非连续切换,会多次进入 Lifecycle.initState: _onInit, Lifecycle.dispose: _onDispose,

测试结果: ---0---1---2---3 当我直接点击tagIndex=3时,会有如下周期: flutter: Lifecycle.initState: tagIndex = 0 flutter: Lifecycle.initState: tagIndex = 2 flutter: Lifecycle.dispose: tagIndex = 2 flutter: Lifecycle.initState: tagIndex = 2 flutter: Lifecycle.initState: tagIndex = 3 flutter: Lifecycle.dispose: tagIndex = 2

关键代码

// Page的配置

class HomePage extends Page<HomeState, Map<String, dynamic>> {
  HomePage()
      : super(
          initState: initState,
          effect: buildEffect(),
          reducer: buildReducer(),
          view: buildView,
          wrapper: keepAliveWrapper,
          dependencies: Dependencies<HomeState>(
              adapter: null,
              slots: <String, Dependent<HomeState>>{
                'topBanner': HomeTopBannerConnector() + BannerComponent(),
                'middleBanner': HomeMiddleBannerConnector() + BannerComponent(),
                'search': HomeSearchConnector() + SearchComponent(),
                // NODE: 由于fish redux 的组件不支持传参,通过冗余Connector来进行数据区分
                'recommendList': RecommendConnector() + HomeListComponent(),
                'designList': DesignConnector() + HomeListComponent(),
                'recruitList': RecruitConnector() + HomeListComponent(),
                'commodityList': CommodityConnector() + HomeListComponent(),
              }),
          middleware: <Middleware<HomeState>>[],
        );

  @override
  ComponentState<HomeState> createState() {
    return HomeStateKeepAliveStf();
  }
}

// Connerctor (其他类似)
class RecommendConnector extends ConnOp<HomeState, HomeListState> {
  @override
  HomeListState get(HomeState state) {
    // tabViewList 在State中的声明==》 Map<TabType, HomeListState> tabViewList = {};
    return state.tabViewList[TabType.recommend];
  }

  @override
  void set(HomeState state, HomeListState subState) {
    state.tabViewList[TabType.recommend] = subState;
  }
}

// 用于查到对应组件
const Map<TabType, String> tabComponentMap = {
  TabType.recommend: 'recommendList',
  TabType.design: 'designList',
  TabType.recruit: 'recruitList',
  TabType.commodity: 'commodityList',
};

TabBarView(
  controller: state.tabController,
  children: tabComponentMap.values.map((v) {
    return KeepAliveWidget(viewService.buildComponent(v));
  }).toList(),
),

在component的使用 image

期望 生命周期正常:init对应一个dispose 或者在Tabbar中非相邻切换时Lifecycle能正常

jing-pei commented 4 years ago
Effect<HomeListState> buildEffect() {
  return combineEffects(<Object, Effect<HomeListState>>{
    Lifecycle.initState: _onInit,
    Lifecycle.dispose: _onDispose,
  });
}
jing-pei commented 4 years ago

不知道 我这种方法是否正确,应该在哪里进行 ctx.state.scrollController?.addListener

另外我在组件implements StateKey 依然存在该问题

 @override
  Object key() {
    return uniqueKey;
  }
zjuwjf commented 4 years ago

1、生命周期都是透传,所以生命周期问题,是flutter内部实现如此; 2、Connector 冗余

// Connerctor (其他类似)
class MyConnector extends ConnOp<HomeState, HomeListState> {
  final String type;

  const MyConnector(this.type);

  @override
  HomeListState get(HomeState state) {
    // tabViewList 在State中的声明==》 Map<TabType, HomeListState> tabViewList = {};
    return state.tabViewList[type];
  }

  @override
  void set(HomeState state, HomeListState subState) {
    state.tabViewList[type] = subState;
  }
}

即可

jing-pei commented 4 years ago

非常感谢,我已测试,是flutter自身的问题