flutter - 如何在 Flutter 中获取有关提供者上下文更改的网络数据
问题描述
我有一个带有一些奇怪功能的 Flutter 应用程序,但它是必需的。该应用程序的 BottomNavigationBar 页面包含在 IndexedStack 中,因此如果您转到此 IndexedStack 的其他页面,页面不会重新加载并保持持久性。
class _MyHomePageState extends State<MyHomePage> {
//...
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: selectedIndex,
children: bottomBarPages(),
),
bottomNavigationBar: BottomNavigationBar(
items: navItems,
currentIndex: selectedIndex,
onTap: _onNavItemTapped,
),
);
}
}
其中一个页面是 ProfilePage,您可以在其中选择用户列表。我使用如下所示的 ChangeNotifier:
class MainUserInfo extends ChangeNotifier {
List<UserInfo> _users;
UserInfo _chosenUser;
//... some get/set/etc methods here
}
其他 BottomNavigationBar 页面之一 TheOtherPage 取决于所选用户 (_chosenUser),在 initState 上它从网络加载数据:
class TheOtherPage extends StatefulWidget {
//...
bool isLoading = true;
@override
void initState() {
super.initState();
getAccountData();
}
void getAccountData() async {
//some fetch happening here
setState(() {
model = response.data;
isLoading = false;
});
}
}
问题是字段 _chosenUser 更改后,我需要 TheOtherPage 从网络加载所选用户的数据。但我不知道如何处理它。如果我使用 context.read 或 context.select 它肯定会跟踪更改的 _chosenUser,但不会获取新选择的数据:
var mainUserInfo = context.read<MainUserInfo>();
//or
var chosenUser = context.select<MainUserInfo, UserInfo>((userInfo) => userInfo.chosenUser);
而且我不想在 UserInfo 对象中保存 TheOtherPage 所需的数据,因为数据太多,并且为 MainUserInfo._users 中的每个用户加载这么多数据不是一种选择。此外,我将能够跟踪加载状态,因为使用“bool Isloading”我可以在获取所需数据时显示一些花哨的占位符。
所以一般的问题是如何使 TheOtherPage 获取 ProfilePage 上 ChangeNotifier 更改字段的数据。也许我的整个方法很糟糕,我不需要在这里使用 Provider 和 ChangeNotifier,我想看看任何建议。谢谢
解决方案
这是 provider 试图解决的一个典型案例:在 2 个小部件之间共享数据
这是你的树结构:
Scaffold
\ IndexedStack
\ ProfilePage <- share MainUserInfo
\ TheOtherPage <- share MainUserInfo
问题是您希望 TheOtherPage 听MainUserInfo
它不听的。(因为initState()
有状态的widget只会被调用一次,即使状态改变了)
我建议你可以听build
方法里面的提供者,并使用FutureBuilder来处理加载状态:
class _TheOtherPageState extends State<TheOtherPage> {
//...
@override
void initState() {
super.initState();
// do nothing here
}
@override
Widget build(BuildContext context) {
// rebuild everytime the MainUserInfo get notified by watching it
// final mainUserInfo = context.watch<MainUserInfo>();
// rebuild everytime the chosenUser change inside MainUserInfo
final chosenUser = context.select<MainUserInfo, UserInfo>((userInfo) => userInfo.chosenUser);
return FutureBuilder(
future: getAccountData(chosenUser).
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.connectionState == ConnectionState.done && snapshot.hasData){
model = snapshot.data;
// return a page with the model
} else {
// return the loading placeholders
}
}
);
}
Future getAccountData(user) async {
//some fetch happening here with the user
// ...
return response.data;
}
}
您还可以尝试一件事:使用const
关键字(如何处理不需要的小部件构建?)
...
body: IndexedStack(
index: selectedIndex,
children: [
ProfilePage(),
const TheOtherPage(), // here
],
),
...
class TheOtherPage extends StatefulWidget {
const TheOtherPage({Key key}) : super(key: key); // and here
@override
_TheOtherPageState createState() => _TheOtherPageState();
}
推荐阅读
- reactjs - Axios 拦截器 - 错误未返回到“then”方法
- flutter - 如何自定义对话框的位置、大小和背景?
- c++ - 为什么 std::vector
::insert 使用 MSVC 2015 编译器比 std::copy 快 5 倍? - c# - 具有不同类型的 C# 索引器属性
- python - AttributeError:“程序”对象没有属性“框架”
- matplotlib - 了解 LogLocator 中的 subs 参数
- java - Spring Boot OAuth2 `AbstractTokenGranter.validateGrantType()` 方法中发生了什么?
- amazon-web-services - Terraform 和 AWS Storage Gateway 磁盘有问题
- html - 电子对话框关闭刷新了我当前的页面
- javascript - 从 NodeJS 项目中提取纯 Javascript