Flutter:如何在多页中使用带有 SharedPreference 和 List<String> 变量的 Riverpod?
Flutter : How to use Riverpod with SharedPreference and List<String> Variable in multipage?
我已经创建了 List<String> favId = [];
变量来存储带有 SharedPreferences 的项目 ID,因此在我重新启动应用程序后收藏的项目 ID 并没有丢失。这是我的 SharedPreferences 方法和 detailDoaPage.dart 中最喜欢的 IconButton :
...
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();
}),
)
除此之外,我还想在 favPage.dart(另一页)中显示带有 ListView.builder 的收藏项。当然,我想从 detailDoaPage.dart 获取 favId。如何在这 2 个页面上实现 provider/riverpod?
这是我的应用程序的预览:
谢谢:)
我推荐的方法是创建一个 StateNotifier 来处理状态以及与 SharedPreferences 的交互。以下内容也简化了小部件中的逻辑。
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);
}
}
用法:
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()),
);
}
}
我已经创建了 List<String> favId = [];
变量来存储带有 SharedPreferences 的项目 ID,因此在我重新启动应用程序后收藏的项目 ID 并没有丢失。这是我的 SharedPreferences 方法和 detailDoaPage.dart 中最喜欢的 IconButton :
...
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();
}),
)
除此之外,我还想在 favPage.dart(另一页)中显示带有 ListView.builder 的收藏项。当然,我想从 detailDoaPage.dart 获取 favId。如何在这 2 个页面上实现 provider/riverpod?
这是我的应用程序的预览:
谢谢:)
我推荐的方法是创建一个 StateNotifier 来处理状态以及与 SharedPreferences 的交互。以下内容也简化了小部件中的逻辑。
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);
}
}
用法:
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()),
);
}
}