[英]How to implement Flutter Riverpod FutureProvider with shared_preferences library?
[英]Flutter Riverpod : How to Implement FutureProvider?
我使用Flutter Riverpod package 來處理 http 請求。 我有簡單的 Http獲取請求以顯示來自服務器的所有用戶,我使用來自Flutter Riverpod package的 FutureProvider 對其進行管理。
class UserGoogleApi {
Future<List<UserGoogleModel>> getAllUser() async {
final result = await reusableRequestServer.requestServer(() async {
final response =
await http.get('${appConfig.baseApiUrl}/${appConfig.userGoogleController}/getAllUser');
final Map<String, dynamic> responseJson = json.decode(response.body);
if (responseJson['status'] == 'ok') {
final List list = responseJson['data'];
final listUser = list.map((e) => UserGoogleModel.fromJson(e)).toList();
return listUser;
} else {
throw responseJson['message'];
}
});
return result;
}
}
class UserProvider extends StateNotifier<UserGoogleModel> {
UserProvider([UserGoogleModel state]) : super(UserGoogleModel());
Future<UserGoogleModel> searchUserByIdOrEmail({
String idUser,
String emailuser,
String idOrEmail = 'email_user',
}) async {
final result = await _userGoogleApi.getUserByIdOrEmail(
idUser: idUser,
emailUser: emailuser,
idOrEmail: idOrEmail,
);
UserGoogleModel temp;
for (var item in result) {
temp = item;
}
state = UserGoogleModel(
idUser: temp.idUser,
createdDate: temp.createdDate,
emailUser: temp.emailUser,
imageUser: temp.emailUser,
nameUser: temp.nameUser,
tokenFcm: temp.tokenFcm,
listUser: state.listUser,
);
return temp;
}
Future<List<UserGoogleModel>> showAllUser() async {
final result = await _userGoogleApi.getAllUser();
state.listUser = result;
return result;
}
}
final userProvider = StateNotifierProvider((ref) => UserProvider());
final showAllUser = FutureProvider.autoDispose((ref) async {
final usrProvider = ref.read(userProvider);
final result = await usrProvider.showAllUser();
return result;
});
設置完成后,我可以像這樣調用showAllUser :
Consumer((ctx, read) {
final provider = read(showAllUser);
return provider.when(
data: (value) {
return ListView.builder(
itemCount: value.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
final result = value[index];
return Text(result.nameUser);
},
);
},
loading: () => const CircularProgressIndicator(),
error: (error, stackTrace) => Text('Error $error'),
);
}),
如果 http 請求沒有必需的參數,那沒問題,但是如果我的 http 請求必需的參數,我就遇到了問題。 我不知道如何處理這個。
假設,我有另一個 http可以顯示來自 id 用戶或 email 用戶的特定用戶。 然后 API 看起來像:
Future<List<UserGoogleModel>> getUserByIdOrEmail({
@required String idUser,
@required String emailUser,
@required String idOrEmail,
}) async {
final result = await reusableRequestServer.requestServer(() async {
final baseUrl =
'${appConfig.baseApiUrl}/${appConfig.userGoogleController}/getUserByIdOrEmail';
final chooseURL = idOrEmail == 'id_user'
? '$baseUrl?id_or_email=$idOrEmail&id_user=$idUser'
: '$baseUrl?id_or_email=$idOrEmail&email_user=$emailUser';
final response = await http.get(chooseURL);
final Map<String, dynamic> responseJson = json.decode(response.body);
if (responseJson['status'] == 'ok') {
final List list = responseJson['data'];
final listUser = list.map((e) => UserGoogleModel.fromJson(e)).toList();
return listUser;
} else {
throw responseJson['message'];
}
});
return result;
}
final showSpecificUser = FutureProvider.autoDispose((ref) async {
final usrProvider = ref.read(userProvider);
final result = await usrProvider.searchUserByIdOrEmail(
idOrEmail: 'id_user',
idUser: usrProvider.state.idUser, // => warning on "state"
);
return result;
});
當我使用usrProvider.state.idUser
從 userProvider 訪問 idUser 時,我收到了這個警告。 The member 'state' can only be used within instance members of subclasses of 'package:state_notifier/state_notifier.dart'.
這與我的問題類似,但在那個問題上我已經知道使用read(userProvider.state)
解決了,但是在FutureProvider中我無法使用ref(userProvider)
獲得相同的結果。
我錯過了什么?
警告:這不是一個長期的解決方案
假設您的 FutureProvider 在每次使用后都被正確處理,這應該是一個合適的解決方法,直到對 Riverpod 的新更改生效。 我做了一個快速測試,看看它確實有效。 確保您定義了這樣的 getter,並且不要覆蓋 StateNotifier 定義的默認值。
class A extends StateNotifier<B> {
...
static final provider = StateNotifierProvider((ref) => A());
getState() => state;
...
}
final provider = FutureProvider.autoDispose((ref) async {
final a = ref.read(A.provider);
final t = a.getState();
print(t);
});
不理想,但似乎是一個很好的解決方法。 我相信 state 在外部無法訪問的目的是確保 state 操作由 StateNotifier 本身處理,因此同時使用吸氣劑不會是世界末日。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.