Flutter : How to use Riverpod with SharedPreference and List<String> Variable in multipage?

2,192

My recommended approach would be to create a StateNotifier that handles the state as well as the interactions with SharedPreferences. The following simplifies the logic in your widgets as well.

final sharedPrefs =
    FutureProvider<SharedPreferences>((_) async => await SharedPreferences.getInstance());

class FavoriteIds extends StateNotifier<List<String>> {
  FavoriteIds(this.pref) : super(pref?.getStringList("id") ?? []);

  static final provider = StateNotifierProvider<FavoriteIds, List<String>>((ref) {
    final pref = ref.watch(sharedPrefs).maybeWhen(
          data: (value) => value,
          orElse: () => null,
        );
    return FavoriteIds(pref);
  });

  final SharedPreferences? pref;

  void toggle(String favoriteId) {
    if (state.contains(favoriteId)) {
      state = state.where((id) => id != favoriteId).toList();
    } else {
      state = [...state, favoriteId];
    }
    // Throw here since for some reason SharedPreferences could not be retrieved
    pref!.setStringList("id", state);
  }
}

Usage:

class DoaWidget extends ConsumerWidget {
  const DoaWidget({Key? key, required this.doa}) : super(key: key);

  final Doa doa;

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final favoriteIds = watch(FavoriteIds.provider);

    return IconButton(
      icon: favoriteIds.contains('') ? Icon(Icons.favorite) : Icon(Icons.favorite_border),
      color: favoriteIds.contains('') ? Colors.red : Colors.grey,
      onPressed: () => context.read(FavoriteIds.provider.notifier).toggle(doa.id.toString()),
    );
  }
}
Share:
2,192
Bill Rei
Author by

Bill Rei

Updated on December 29, 2022

Comments

  • Bill Rei
    Bill Rei over 1 year

    I've create List<String> favId = []; variable to store item's ID with SharedPreferences, so the favorited items ID didnt lost after I restart the application. And here is my SharedPreferences method and favorite IconButton in detailDoaPage.dart :

    ...
    static List<String> favId = [];
    
      getData() async {
        SharedPreferences pref = await SharedPreferences.getInstance();
        setState(() {
          favId = pref.getStringList("id") ?? [];
        });
      }
    
      void initState() {
        super.initState();
        getIds();
      }
    
      getIds() async {
        favId = getData();
      }
    
      void saveData() async {
        SharedPreferences pref = await SharedPreferences.getInstance();
        pref.setStringList("id", favId);
      }
    ...
    IconButton(
                        icon: Icon(
                          favId.contains(doa.id.toString())
                              ? Icons.favorite
                              : Icons.favorite_border,
                          color: favId.contains(doa.id.toString())
                              ? Colors.red
                              : Colors.grey,
                        ),
                        onPressed: () => setState(() {
                          doa.fav = !doa.fav;
                          if (favId.contains(doa.id.toString())) {
                            favId.removeWhere(
                                (element) => element == doa.id.toString());
                          } else {
                            favId.add(doa.id.toString());
                          }
                          saveData();
                          favId.sort();
                        }),
                      )
    

    Beside that, I also want to show the favorited item's with ListView.builder in favPage.dart (another page). Of course I want get the favId from detailDoaPage.dart. How can I implement the provider/riverpod across this 2 pages?

    Here is the preview of my app :

    enter image description here

    Thank you :)

    • ambiguous58
      ambiguous58 about 3 years
      I can try to point you in the right direction. What you want to do is very similar to the todos example in the riverpod docs. You can treat yourbool isFavoriteDoa similar to how they treat bool completed. It's only two files of code take a look at them and try to implement the same solution in your app.
    • Bill Rei
      Bill Rei about 3 years
      @ambiguous58 whoa, thank you so much for your advice. Yes I will learn for it :)
  • Bill Rei
    Bill Rei about 3 years
    I'm sorry, I'm still little confused. This is my code for this my two page (detailDoaPage.dart & favPage.dart) replit.com/join/nlzhbikh-nabilrei . Do you want to help me to revise my code with yours? Thank you :)
  • Alex Hartford
    Alex Hartford about 3 years
    Happy to help, glad we could get your solution working! Thanks for introducing the replit tool to me as well.
  • LearnFlutter
    LearnFlutter about 2 years
    Hi, is there a possibility you could help on my issue where i would like to use riverpod. – stackoverflow.com/questions/70980002/…