使用Riverpod展示多API请求数据时的模型属性访问报错问题
问题解决:Riverpod中Record类型数据的访问错误
问题原因
你通过getItemByUser返回的是Dart的匿名Record(记录类型)(UserTable, ItemModel),这种类型没有userName或itemName这类直接的getter方法,直接访问data.userName会触发类型错误。
解决方案
有两种方式可以正确访问Record中的数据:
方案1:使用位置索引访问匿名Record
匿名Record的成员需要通过$1、$2这样的位置索引来获取($1对应第一个返回值,$2对应第二个),修改展示代码即可:
ref.watch(getProfileAndItem(uid)).when( data: (data) => Column( children: [ Text(data.$1.userName), // 获取第一个元素UserTable实例,再访问userName Text(data.$2.itemName) // 获取第二个元素ItemModel实例,再访问itemName ], ), error: (error, stackTrace) => ErrorText(error: error.toString()), loading: () => const Loader(), ));
方案2:使用命名Record提升可读性
如果希望代码更直观,可以改用命名Record,需要同时修改数据获取和展示的代码:
- 修改
getItemByUser方法的返回类型和返回值:
Future<({UserTable user, ItemModel item})> getItemByUser(String uid) async { try { final value = await Future.wait([ http.get(Uri.parse('${API.getpurchaseItemByUID}?uid=$uid')), http.get(Uri.parse('${API.getUserProfileByUID}?uid=$uid')) ]); final item = jsonDecode(value[0].body); final profile = jsonDecode(value[1].body); // 返回带命名的Record return ( user: UserTable.fromJson(profile[0]), item: ItemModel.fromJson(item[0]) ); } catch (error) { throw error; } }
- 更新Provider的泛型定义:
final getProfileAndItem = FutureProvider.family<({UserTable user, ItemModel item}), String>((ref, String uid) async { return ref.watch(itemUserProvider).getItemByUser(uid); });
- 在展示代码中通过命名访问数据:
ref.watch(getProfileAndItem(uid)).when( data: (data) => Column( children: [ Text(data.user.userName), // 通过命名user获取UserTable实例 Text(data.item.itemName) // 通过命名item获取ItemModel实例 ], ), error: (error, stackTrace) => ErrorText(error: error.toString()), loading: () => const Loader(), ));
内容的提问来源于stack exchange,提问作者hayek
相关产品推荐
相关产品推荐

