gpt4 book ai didi

flutter - 如何在Navigator中使用ChangeNotifier

转载 作者:行者123 更新时间:2023-12-03 03:57:00 25 4
gpt4 key购买 nike

在我的应用程序中,我有一个模型来存储在我的应用程序中登录的用户。

class AuthenticationModel extends ChangeNotifier {
User _user;
User get user => _user;

void authenticate(LoginData loginData) async {
// _user = // get user from http call
notifyListeners();
}

void restoreUser() async {
//_user = // get user from shared prefs
notifyListeners();
}
}

该模型已注册在小部件树的顶部:
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => AuthenticationModel(),
child: MaterialApp(
title: 'My App',
initialRoute: '/',
routes: {
'/': (context) => PrehomeScreen(),
'/home': (context) => HomeScreen()
},
),
);
}
}

在小部件树下的某个地方,我有一个调用Model的按钮:
          child: Consumer<AuthenticationModel>(
builder: (context, authModel, child) {
return MyCustomButton(
text: 'Connect',
onPressed: () {
authModel.authenticate(...)
},
);
},
),

现在,我想在某个地方,当用户在模型中不为null时,听听 AuthenticationModel上的更改以触发 Navigator.pushReplacmentNamed('/home')

我试图在Prehome的构建器中做到这一点:
class PrehomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<AuthenticationModel>(
builder: (context, authModel, child) {
if (authModel.user != null) {
Navigator.of(context).pushReplacementNamed("/home")
}
return Container(
child: // Prehome UI
);
},
);
}
}

但这样做时出现错误:
════════ (2) Exception caught by widgets library ═══════════════════════════════════════════════════
setState() or markNeedsBuild() called during build.
The relevant error-causing widget was:
Consumer<AuthenticationModel> file:///Users/pierre.degand/Projects/cdc/course_du_coeur/lib/Prehome.dart:13:12
═══════════════════════════════════════════════════════════════════════════════

如何设置这样的监听器?在这样的模型更改上触发导航是否是一种好习惯?

谢谢

编辑:我找到了一种使这项工作的方法。我没有在PrehomeScreen构建器中使用 Consumer,而是使用了以下代码:
class PrehomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {

Provider.of<AuthenticationModel>(context).addListener(() {
Navigator.of(context).pushReplacementNamed("/home");
});

return Container(
child: // UI
);
}
}

它工作正常,在模型更改时执行导航。但是控制台中有一条错误消息(打印了3次):
════════ (4) Exception caught by foundation library ════════════════════════════════════════════════
Looking up a deactivated widget's ancestor is unsafe.
════════════════════════════════════════════════════════════════════════════════════════════════════

该应用程序不会崩溃,因此,现在我可以接受。
我仍然想知道这是否是一个好方法。

最佳答案

我更喜欢使用Stream或rxdart PublishSubject BehaviourSubject收听任何 Activity 或管理全局应用程序数据。

我使用bloc模式实现它。基本上,区块模式就像redux一样,react意味着创建一个包含所有应用程序数据的中央数据集,而您不必进行 Prop 钻探。

您可以像这样创建Stream。

import 'package:rxdart/rxdart.dart';

class AbcBloc {
BehaviorSubject<bool> _connectivity;
AbcBloc() {
_connectivity = BehaviorSubject<bool>();
}
// stream
Stream<bool> get connectivity => _connectivity.stream;
// sink
Function(bool) get updateConnectivity => _connectivity.sink.add;
dispose(){
_connectivity.close();
}
}

void createAbcBloc() {
if (abcBloc != null) {
abcBloc.dispose();
}
abcBloc = AbcBloc();
}

AbcBloc abcBloc = AbcBloc();



现在您可以从任何地方访问该abcBloc变量,并像这样收听连接性变量
import './abcBloc.dart';
void listenConnectivity(){

abcBloc.connectivity.listen((bool connectivety){

here you can perform your operations
});
}



您可以从abcBloc.updateConnectivity(false);更新连接。
每次执行任何更改时,都会调用侦听器。

记住您必须调用一次listenConnectivity()才能将其激活;

关于flutter - 如何在Navigator中使用ChangeNotifier,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60304511/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com