简体   繁体   English

对多个页面使用相同的riverpod state 提供程序

[英]Using same riverpod state provider for multiple pages

I I'm using provider for state management (actually riverpod ) In my project I have a tabview and use each tab for a category and each shows news list.我正在使用提供程序进行 state 管理(实际上是riverpod )在我的项目中,我有一个 tabview 并将每个选项卡用于一个类别,每个选项卡都显示新闻列表。 tabview size is not fix and I use same page for all tabs and pass category id to page. tabview 大小不固定,我对所有选项卡使用相同的页面并将类别 ID 传递给页面。

The problem is that newsProvider allways keep last category id and all pages show same news list.问题是 newsProvider 总是保留最后一个类别 ID,并且所有页面都显示相同的新闻列表。 Who I can separate newsProvider list for each pages?谁我可以为每个页面单独列出 newsProvider?

//create tabview in my stateFullWidget
@override
Widget build(BuildContext context) {
   return Scaffold(
   body: DefaultTabController(
     length: europeanCountries.length, // europeanCountries has dynamic size
         child: new Scaffold(
            appBar: new AppBar(
                 
            flexibleSpace: new Column( 
               children: [
                  new TabBar( 
                      tabs: europeanCountries.map<Widget>((e) => getTab(e, FontAwesomeIcons.newspaper)).toList()),
                    ],
                  ),
                ),

               // dynamically create NewsList and pass category id
                body: TabBarView(children: europeanCountries.map((catItem) => NewsList(category: Category(title: catItem.title, id:catItem.id))).toList()),
              ),
            )
       )
 }

class NewsList extends StatefulWidget {
  Category category;

  NewsList({this.category});

  @override
  State<StatefulWidget> createState() {
    return _NewsListState(category:category);
  }
}

class _NewsListState extends State<NewsList> with AutomaticKeepAliveClientMixin<NewsList> {
  Category category;

  _NewsListState({this.category});
  
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      context.read(newsProvider).getNewsList(category.id);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Consumer(builder: (ctx, watch, child) {
      return watch(newsProvider.state).map(
        init: (value) {
          return Container();
        },
        loading: (value) {
          return Container(
            child: Center(
              child: CircularProgressIndicator(),
            ),
          );
        },
        success: (value) {
          return Container(child: getNewsItem(value.newsList));
        },
        serverError: (value) {
          return Container();
        },
      );
    });
  }

  @override
  bool get wantKeepAlive => true;
}




final newsProvider = StateNotifierProvider.autoDispose<NewsListNotifier>((ref) {
  var newsService = ref.watch(newsServiceProvider);
  return NewsListNotifier(newsService);
});

class NewsListNotifier extends StateNotifier<NewsListState> {
  final NewsService serviceRepository;


  NewsListNotifier(this.serviceRepository) : super(NewsListState.init());


  getNewsList(int catID) async {
    state = NewsListState.loading();
    DataResponse request = await serviceRepository.getNewsList(catID);
    request.maybeWhen(
      success: (value) {

        if (value.data != null) {
          state = NewsListState.success(newsList: value.data);
        }
      },
      error: (error) {
        state = NewsListState.serverError(error);
      },
      orElse: () {},
    );
  }

}

I finally find the answer.我终于找到了答案。 thanks @EdwynZN By using family keyword, I can create some thing like a family for each category谢谢@EdwynZN 通过使用family关键字,我可以为每个类别创建一些类似家庭的东西

class NewsList extends StatefulWidget {
  Category category;

  NewsList({this.category});

  @override
  State<StatefulWidget> createState() {
    return _NewsListState(category:category);
  }
}


class _NewsListState extends State<NewsList> with AutomaticKeepAliveClientMixin<NewsList> {
  Category category;

  _NewsListState({this.category});
  
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
     
      // add category.id to newsProvider, instead of getNewsList()
      context.read(newsProvider(category.id)).getNewsList();
    });
  }


  @override
  Widget build(BuildContext context) {
    return Consumer(builder: (ctx, watch, child) {

      //newsProvider(category.id) just listen to specific category id and not listen to all ids
      return watch(newsProvider(category.id).state).map( 
        init: (value) {
          return Container();
        },
        loading: (value) {
          return Container(
            child: Center(
              child: CircularProgressIndicator(),
            ),
          );
        },
        success: (value) {
          return Container(child: getNewsItem(value.newsList));
        },
        serverError: (value) {
          return Container();
        },
      );
    });
  }


  @override
  bool get wantKeepAlive => true;
}

//using family here and pass <My State, Category id>
final newsProvider = StateNotifierProvider.family<NewsListNotifier, int>((ref, catID) {
  var newsService = ref.watch(newsServiceProvider);
  return NewsListNotifier(newsService, catID);
});

class NewsListNotifier extends StateNotifier<NewsListState> {
  final NewsService serviceRepository;
  int catID;

  NewsListNotifier(this.serviceRepository, this.catID) : super(NewsListState.init());


  getNewsList() async {
    state = NewsListState.loading();
    DataResponse request = await serviceRepository.getNewsList(catID, page, 20);

    request.maybeWhen(
      success: (value) {

        if (value.data != null) {
          state = NewsListState.success(newsList: value.data);
        }
      },
      error: (error) {
        state = NewsListState.serverError(error);
      },
      orElse: () {},
    );
  }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM