Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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. tabview size is not fix and I use same page for all tabs and pass category id to page.

The problem is that newsProvider allways keep last category id and all pages show same news list. Who I can separate newsProvider list for each pages?

//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: () {},
    );
  }

}
question from:https://stackoverflow.com/questions/65646507/using-same-riverpod-state-provider-for-multiple-pages

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
389 views
Welcome To Ask or Share your Answers For Others

1 Answer

I finally find the answer. thanks @EdwynZN By using family keyword, I can create some thing like a family for each category

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: () {},
    );
  }

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...