英文:
Riverpod 2.0 FutureProvider correct usage
问题
我有一个字典JSON文件,我想在我的应用程序启动时加载一次,但我不确定应该如何做。我的第一种方法是这样的:
@Riverpod(keepAlive: true)
class AppDictionary extends _$AppDictionary {
@override
FutureOr<List<DictionaryEntry>> build() async {
return await _parseDictionary();
}
Future<List<DictionaryEntry>> _parseDictionary() async {
try {
final response = await rootBundle.loadString('assets/dict.json');
final data = await json.decode(response) as List<dynamic>;
final parsedData = data
.map((e) => DictionaryEntry.fromMap(e as Map<String, dynamic>))
.toList();
return parsedData;
} catch (e) {
print(e);
rethrow;
}
}
}
在我的初始页面中,我做了这个:
final asyncDictionary = ref.watch(appDictionaryProvider);
if (asyncDictionary.isLoading) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
它运行得很好。但是在Riverpod的文档中阅读FutureProvider时,我发现我可以这样做:
@riverpod
Future<List<DictionaryEntry>> loadDictionary(LoadDictionaryRef ref) async {
try {
final response = await rootBundle.loadString('assets/dict.json');
final data = await json.decode(response) as List<dynamic>;
final parsedData = data
.map((e) => DictionaryEntry.fromMap(e as Map<String, dynamic>))
.toList();
return parsedData;
} catch (e) {
print(e);
rethrow;
}
}
第二种方法也有效,所以我想知道哪种方法更好。此外,第二种方法,每次我调用ref.watch()
时,它会重新加载吗?或者一旦加载了它就不会再次运行?
谢谢。
英文:
i have a dictionary JSON file that i want to load just one time when my application starts and i'm not sure about how i should do that. My first approach was doing this
@Riverpod(keepAlive: true)
class AppDictionary extends _$AppDictionary {
@override
FutureOr<List<DictionaryEntry>> build() async {
return await _parseDictionary();
}
Future<List<DictionaryEntry>> _parseDictionary() async {
try {
final response = await rootBundle.loadString('assets/dict.json');
final data = await json.decode(response) as List<dynamic>;
final parsedData = data
.map((e) => DictionaryEntry.fromMap(e as Map<String, dynamic>))
.toList();
return parsedData;
} catch (e) {
print(e);
rethrow;
}
}
}
And in my initial page i did this
final asyncDictionary = ref.watch(appDictionaryProvider);
if (asyncDictionary.isLoading) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
And it is working fine. But reading about FutureProvider in Riverpod's documentation, i saw that i could do it this way
@riverpod
Future<List<DictionaryEntry>> loadDictionary(LoadDictionaryRef ref) async {
try {
final response = await rootBundle.loadString('assets/dict.json');
final data = await json.decode(response) as List<dynamic>;
final parsedData = data
.map((e) => DictionaryEntry.fromMap(e as Map<String, dynamic>))
.toList();
return parsedData;
} catch (e) {
print(e);
rethrow;
}
}
And the second way also worked, so i'm wondering which approach is the best. Also, the second way, everytime i call ref.watch( )
will it load it again? Or once it's loaded it will not run again?
Thanks
答案1
得分: 2
第一种方式是基于类的提供程序,创建一个可见的 Notifier 子类来管理状态,并提供可能的变异方法来更新该状态。
第二种方式是基于函数的提供程序,创建一个隐藏的 Notifier 子类来管理状态,但不提供放置变异方法以更新状态的地方。当通知程序基于来自其他外部输入的输入时,而不是通过方法调用来触发变异时,可以使用这种方式。不使用生成器的这种策略的示例包括 Provider、FutureProvider 和 StreamProvider。
英文:
The first way is a class-based provider, creating a visible Notifier subclass to manage the state as well as provide possible mutation methods to update that state.
The second way is a function-based provider, creating a hidden Notifier subclass to manage the state, but does not provide a place to put mutation methods to update the state. You would use this when the notifier is based on inputs from other external inputs, rather than being driven by method calls to trigger mutations. Examples of this strategy without using the generator would be Provider, FutureProvider, and StreamProvider.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论