har*_*B10 6 dart flutter flutter-provider
我在使用 Flutter Provider 时遇到了问题......我的流程是这样的:登录用户 ID 被传递给新的小部件后 -> 从那里执行保存到数据库,然后重定向到新的小部件(仪表板)。
这是登录后小部件的代码:
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: ListView(
children: <Widget>[
Container(
margin: EdgeInsets.all(8.0),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0))),
child: InkWell(
onTap: () {
var user = Provider.of<UserRepository>(context);
user.savePreference(user.user.id, "Something");
user.navigateToNewPage(Dashboard(), context);
print(user.user.id);
},
Run Code Online (Sandbox Code Playgroud)
这有效:
user.savePreference(user.user.id, "Something");
Run Code Online (Sandbox Code Playgroud)
但这导致了一个问题:
user.navigateToNewPage(Dashboard(), context);
Run Code Online (Sandbox Code Playgroud)
在仪表板小部件中,我正在创建:
Widget build(BuildContext context) {
var user = Provider.of<UserRepository>(context);
Run Code Online (Sandbox Code Playgroud)
在 UserRepository 我有这个:
class UserRepository with ChangeNotifier {
User user;
Status _status = Status.Uninitialized;
Status get status => _status;
User get getUser => user;
UserRepository.instance();
Future<void> navigateToNewPage(Widget page, BuildContext context) {
Navigator.push(context, MaterialPageRoute(builder: (context) => page));
}
Run Code Online (Sandbox Code Playgroud)
我知道这个话题已经解决了问题,但找不到适合我的问题的任何内容。
Bak*_*ker 51
MaterialApp
> provider(Screen A)
> Screen B
Run Code Online (Sandbox Code Playgroud)
如果Provider在屏幕 A 中实例化,则在Navigator.push从 A之后无法在屏幕 B 中访问它?B.
因为Provideris an InheritedWidgetand在其 Screen A范围之外Navigator使用。(请参阅下面的详细信息。)MaterialApp contextcontext
Provider向上移动到公共父级,MaterialApp context允许屏幕 A 和 B 继承其状态/上下文。
provider(MaterialApp)
> Screen A
> Screen B
Run Code Online (Sandbox Code Playgroud)
例子
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
/// wrap MaterialApp in Provider widget
return ChangeNotifierProvider(
create: (context) => ColorModel(), // ? create/init your state model
child: MaterialApp(
home: ScreenA()
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
Provider是基于InheritedWidget. 只有子小部件可以继承父小部件的状态。
Provider需要是任何想要访问“提供”状态对象的小部件树的根小部件。Navigator.push(context)在屏幕上不使用的context从屏幕A.
context来自MaterialApp.Navigator.push(context) 实际上是 Navigator.of(context).pushNavigator.of(context)意味着:搜索这个上下文层次结构,直到找到一个实例化导航器的上下文
Navigator在MaterialApp.Navigator,否则您将使用默认值。Navigator的context就是MaterialApp.MaterialApp),没有屏幕A.上下文
contextA内部看起来是“实例化的” 。MaterialApp context,而不是屏幕 A 的子项context。Provider context 范围,如果在屏幕 A 中定义,则不包括屏幕 B屏幕 A ? 乙
Navigator.push(context, MaterialPageRoute(builder: (context) => ScreenB()))
Run Code Online (Sandbox Code Playgroud)
实际上是:
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ScreenB()))
Run Code Online (Sandbox Code Playgroud)
这就像:
Navigator.of(MaterialApp).push(
MaterialPageRoute(builder: (MaterialAppContext) => ScreenB())
)
Run Code Online (Sandbox Code Playgroud)
所以屏幕 B在屏幕 A之下MaterialApp context,而不是在屏幕 A之下,context因此无法访问屏幕 AProvider及其context.
尝试将位于 Scaffold 下方的小部件树的一部分提取到单独的小部件。您现在使用的上下文用于构建您的顶级小部件,该小部件还没有导航器。
生成的代码应如下所示:
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: LoginWidget()
Run Code Online (Sandbox Code Playgroud)
class LoginWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
Container(
margin: EdgeInsets.all(8.0),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0))),
child: InkWell(
onTap: () {
var user = Provider.of<UserRepository>(context);
user.savePreference(user.user.id, "Something");
user.navigateToNewPage(Dashboard(), context);
print(user.user.id);
},
...
}
}
Run Code Online (Sandbox Code Playgroud)
contextProvider.of(context) 的参数必须是您定义的提供程序的子项。
@override
Widget build(BuildContext context) {
// !important here, Scaffold.of(context) returns null
return Scaffold(
appBar: AppBar(title: Text('Demo')),
body: Builder(
builder: (BuildContext context) {
return FlatButton(
child: Text('BUTTON'),
onPressed: () {
// here, Scaffold.of(context) returns the locally created Scaffold
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('Hello.')
));
}
);
}
)
);
}
Run Code Online (Sandbox Code Playgroud)
官方示例:https : //api.flutter.dev/flutter/widgets/BuildContext-class.html
这是我的代码:
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [ChangeNotifierProvider<SomeModel>(
create: (context){
return SomeModel();
},
),],
child: Builder(builder: (BuildContext context){
BuildContext rootContext = context;
return Container(
//Here to use rootContext is safe
//Provider.of<SomeModel>(rootContext, listen: false);
);
}),
);
}
Run Code Online (Sandbox Code Playgroud)
这就是我们与多个提供商一起使用的方式
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => GeneralProvider(),
),
],
child: MaterialApp(
home: InitPage(),
onGenerateRoute: MyRouter.generateRoute,
initialRoute: '/InitPage',
debugShowCheckedModeBanner: false,
title: 'Eray',
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25151 次 |
| 最近记录: |