Provider 包使用InheritedWidget. 当我在对话框中时想访问提供程序时,这是一个问题。如果我使用加载对话框
showDialog(... builder: (context) => MyDialog);
Run Code Online (Sandbox Code Playgroud)
我无法访问任何东西,InheritedWidget因为我的对话框不是主小部件树的一部分。这也意味着我无法访问我的 Provider 提供商,对吗?
我的问题是:如果它不是主应用程序小部件树的一部分,我如何在对话框中访问我的提供程序?
final firebaseAuth = Provider.of<FirebaseAuth>(context);
Run Code Online (Sandbox Code Playgroud)
我在使用BLoCs. 如果我尝试在对话框中通过 检索它们InheritedWidget,它们将失败。我已经通过BLoC在构造函数中传递了来解决这个问题,但这似乎违背了InheritedWidgets.
我想我现在至少有一个模糊的想法,
如何在我的应用程序中使用BLoC,Stream Builder
和继承的小部件(或模型)
(没有什么特别的,但对我来说需要时间),
但玩Scoped模型
我有一个存在的危机:
我觉得他们大多数可以做同样的事情,或者
至少我可以
用它们中的任何一个获得相同的明显效果,
但我没有能力去理解
何时 以及为什么一个比另一个好.
我故意保持开放的问题不要因为我而讨厌我,
但我希望能更好地理解我正在做的事情
以及使用这一个或另一个事件在幕后发生的事情.
谢谢你的耐心等待.弗朗切斯科
Ps:我不能添加'范围模型'标签,如果可以的话,
它可能与像我这样的新手有关
当我尝试在应用加载时从本地存储读取数据时,出现了抖动问题。
我有一个继承的小部件,其中包含当前用户的身份验证信息。应用加载时,我想查看会话令牌的本地存储。如果会话令牌存在,我想用此信息更新继承的窗口小部件。
我的屏幕是动态的。如果知道用户已通过身份验证,则将他们带到请求的屏幕,否则将他们带到注册屏幕。
我遇到的问题是我无法initState()通过依赖于继承的窗口小部件(我的路由器窗口小部件)的窗口小部件中的方法更新继承的窗口小部件的状态。
应用加载并更新继承的小部件时,如何从本地存储中读取信息?
运行应用程序时出错:
flutter: ??? EXCEPTION CAUGHT BY WIDGETS LIBRARY ????????????????????????????????????????????????????????????
flutter: The following assertion was thrown building _InheritedAuthContainer:
flutter: inheritFromWidgetOfExactType(_InheritedAuthContainer) or inheritFromElement() was called before
flutter: RootState.initState() completed.
flutter: When an inherited widget changes, for example if the value of Theme.of() changes, its dependent
flutter: widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor
flutter: or an initState() method, then the rebuilt dependent widget will not reflect …Run Code Online (Sandbox Code Playgroud) 我看到我可以build()像这样在方法内部访问InheritedWidgets :final inheritedWidget = ChronoApp.of(context);但是如果我想在其他地方访问它(例如在initState()没有上下文的情况下)怎么办。我该怎么做?
InheritedWidget 的Flutter文档说
\n\n\n有效地沿树传播信息的小部件的基类。
\n要从构建上下文获取特定类型的继承窗口小部件的最近实例,请使用 BuildContext.inheritFromWidgetOfExactType。
\n当以这种方式引用继承的小部件时,\n当继承的小部件本身更改状态时,将导致使用者重建。
\n
鉴于 Flutter 中的小部件是不可变的,并且在示例代码中..
\nclass FrogColor extends InheritedWidget {\n const FrogColor({\n Key key,\n @required this.color,\n @required Widget child,\n }) : assert(color != null),\n assert(child != null),\n super(key: key, child: child);\n\n final Color color;\n\n static FrogColor of(BuildContext context) {\n return context.inheritFromWidgetOfExactType(FrogColor);\n }\n\n @override\n bool updateShouldNotify(FrogColor old) => color != old.color;\n}\nRun Code Online (Sandbox Code Playgroud)\n颜色属性final因此无法重新分配。假设这个小部件位于树的顶部,就像大多数示例一样,它什么时候会有用。对于要替换的小部件,必须创建一个新实例。
据推测,在完成此操作的情况下,也将创建作为子级传递的任何内容的新实例,从而导致该子级的后代也进行重建,创建其子级的新实例等。
\n无论如何,最终还是重建了整棵树。inheritFromWidgetOfExactType那么,当 InheritedWidget 实例的数据永远不会改变该实例时,使用 using 进行选择性更新是没有意义的?
编辑:
\n这是我不明白的最简单的例子,我可以将它们放在一起。\n在这个例子中,“更改” …
在将InheritedWidget添加到应用程序后,我认识到当我使用Pop()从详细信息屏幕返回列表时,ListView失去了滚动位置(选定的项目索引)。
我知道小部件可以随时重建,但也许有人可以提出解决方案,而无需手动处理缓存。
在实现InheritedWidget之前,PS Scroll位置很好
Flutter中有两个函数:
在文档中,他们说:findAncestorWidgetOfExactType相对昂贵(在树的深度中为O(N) )。
dependentOnInheritedWidgetOfExactType 的复杂度为O(1),并且有一个小的常数因子。
任何人都可以解释为什么?为什么第一个比另一个贵?
谢谢
Let's say I need a user service which has all my user variables and functions, and another item service with all item variables and functions, etc etc. I want all this data and functions available throughout the project, passing the user data where it's needed, for example.
I suspect it has something to do with inherited widgets, but how does that work? Like, I see how I could use one inherited widget at the root level, but am I supposed …
导航到新窗口小部件后,我在尝试访问InheritedWidget时遇到问题.
我有这样的顶级小部件
class App extends StatelessWidget{
build(context){
return MaterialApp(
title: 'Iniciar Sesion',
home: LoginBlocProvider(child: WelcomeScreen()),
);
}
}
Run Code Online (Sandbox Code Playgroud)
然后WelcomeScreen有一个导航到LoginScreen的按钮
class WelcomeScreen extends StatelessWidget {
@override Widget build(BuildContext context){
return Scaffold(
body: Center(child: MyButton)
);
}
}
class MyButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
shape: StadiumBorder(),
child: Text('Ingresar', style: TextStyle(color: Colors.black)),
elevation: 5.0,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) =>LoginScreen()
));
}
);
}
}
Run Code Online (Sandbox Code Playgroud)
最后在LoginScreen中我想访问InheritedWidget
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => …Run Code Online (Sandbox Code Playgroud) 我收到此错误:
I/flutter (29346): ??? EXCEPTION CAUGHT BY WIDGETS LIBRARY ????????????????????????????????????????????????????????????
I/flutter (29346): The following assertion was thrown building MainLogic(dirty, state: _MainLogic#9c794):
I/flutter (29346): setState() or markNeedsBuild() called during build.
I/flutter (29346): This InhWidget widget cannot be marked as needing to build because the framework is already in the
I/flutter (29346): process of building widgets. A widget can be marked as needing to be built during the build phase
I/flutter (29346): only if one of its ancestors is currently building. This …Run Code Online (Sandbox Code Playgroud) 需要了解什么时候应该Bloc模式以及Bloc的生命周期(如何释放持有内存的对象)
我有一个屏幕,我从服务器获取数据,数据将仅用于单个屏幕。我正在使用 Bloc 模式来显示数据。
使用 Bloc 模式时,我有一个正在使用 StatelessWidget 的屏幕。我正在尝试处理“WillPopScope”上的流。一旦被处置,流就不能再使用。因为访问同一屏幕会导致崩溃,因为我用 Bloc 包装了 MaterialApp。
final _leaderBoardList = StreamController<List<dynamic>>.broadcast();
Run Code Online (Sandbox Code Playgroud)
dispose() {
print('_leaderBoardList disposed');
_leaderBoardList.close();
}
Run Code Online (Sandbox Code Playgroud)
LeaderBoardProvider(
child: MaterialApp(
title: 'Table View Fetch',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: HomeScreen(),
),
);
Run Code Online (Sandbox Code Playgroud)
Widget build(BuildContext context) {
print(' ListView fetch Build called');
final bloc = LeaderBoardProvider.of(context);
bloc.fetchLeaderBoards();
return WillPopScope(
onWillPop: () async {
//bloc.dispose();
return true;
},
child: bodyStack(context, bloc),
);
}
Run Code Online (Sandbox Code Playgroud)
第一个问题,假设我创建一个广播流并删除“WillPopScope”中的代码处理,那么一切都会按预期工作,但我认为,这样,我的 Bloc 就可以为应用程序生命周期保留内存。
第二个问题 …
我需要一些帮助来理解如何从继承的小部件获取数据。
我通常使用直接从构建方法从我的小部件获取参数
@override
Widget build(BuildContext context) {
//THIS METHOD
var data = StateContainer.of(context).data;
return Container(child:Text("${data.parameter}"));
}
Run Code Online (Sandbox Code Playgroud)
但是这个方法不能从 initState 调用,因为还没有 buildContext 。
我需要在 initState 方法中使用该参数(我在其中调用了从服务器获取的数据,并且需要将该数据传递给我的函数),那么,我该怎么做呢?
@override
void initState() {
otherData = fetchData(data);
super.initState();
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用 didChangeDipendencies() 但每次重建视图时都会调用它(从屏幕弹出等),所以它不是我想要使用的,也不是 FutureBuilder 小部件。
有什么建议吗?
我有以下设置:
MaterialApp(home:SplashScreen)
SplashScreen(
///do some auth checks then
Navigator.of(context).push( MaterialPageRoute(
builder: (_) => StateInheritedWidget(
user: userData,
child: HomePage(),
)))
)
Run Code Online (Sandbox Code Playgroud)
然后我HomePage的FAB推动了一条新路线。这条新路线无法访问我继承的窗口小部件的上下文。
是不可能InheritedWidget在新的路线中获得上下文的,还是有解决此问题的方法?
更新资料
这是我的MaterialApp的构建器属性
builder: (context,child){
///Doing some auth stuff here
return new StateInheritedWidget(
user: userData,
child: userData==null?const SplashScreen(child: const LoginPage(),):
const SplashScreen(child: const HomePage(),),
);
},
Run Code Online (Sandbox Code Playgroud)
我的SplashScreen构建方法:
return !_load? new Scaffold(
body: new Center(
child: new Text('Splash'),
),
):this.widget.child;
Run Code Online (Sandbox Code Playgroud)
这些是我得到的错误。
第一个似乎与Drawer我的中的有关HomePage:
I/flutter (12688): ??? EXCEPTION CAUGHT BY WIDGETS LIBRARY …Run Code Online (Sandbox Code Playgroud) flutter ×13
inherited-widget ×13
dart ×9
bloc ×2
performance ×1
scoped-model ×1
state ×1
widget ×1