我正在使用提供程序来管理我的应用程序状态。这是我的实现方式。
hypnose.dart
class _HypnoseAppState extends State<HypnoseApp> {
@override
Widget build(BuildContext context) {
UserService userService = UserService();
AudioUtilService audioUtilService = AudioUtilService();
return MultiProvider(
providers: [
ChangeNotifierProvider<UserService>.value(
value: userService,
),
ChangeNotifierProvider<AudioUtilService>.value(
value: audioUtilService,
)
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: Globals.title,
theme: ThemeData(primarySwatch: Colors.cyan),
darkTheme: ThemeData.dark(),
initialRoute: '/',
routes: {
'/': (BuildContext context) => WelcomeScreen(userService),
'/home': (BuildContext context) => HomePageSwitcher(),
'/audiocreate': (BuildContext context) => AudioCreateScreen()
}),
);
}
}
home_switcher.dart
class HomePageSwitcher extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<UserService>(
builder: (BuildContext context, UserService userService, Widget child) {
return Scaffold(
appBar: AppBar(),
drawer: Drawer(
child: Column(
children: <Widget>[
UserAccountsDrawerHeader(
accountEmail: Text(userService.loggedInUser.email),
accountName: Text(userService.loggedInUser.name),
currentAccountPicture:
Image.network(userService.loggedInUser.avatar),
)
],
),
),
body: Center(
child: RaisedButton(
child: Text('Sign out'),
onPressed: () async {
await userService.signOut();
Navigator.pushNamed(context, '/');
},
),
));
},
);
}
}
user_service.dart
class UserService extends ChangeNotifier {
// Get auth instances
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
// Store reference of user collection
final CollectionReference userDb = Firestore.instance.collection('user');
// Master instance of logged in user
User _loggedInUser;
// Getter to access loggedInUser
User get loggedInUser {
return _loggedInUser;
}
PublishSubject<AuthState> _authStateSubject = PublishSubject();
.... other code
现在这里的问题是,每次我在首页上热加载时,我都会开始收到NoSuchMethodError,因为它表示像电子邮件,名称等属性是在null上调用的,我认为这意味着状态为丢失。我该如何克服呢?我在做错什么吗?
答案 0 :(得分:3)
build方法的设计方式应使其纯净/无副作用。这是因为许多外部因素都可以触发新的小部件构建,例如:
Route pop/push
Screen resize, usually due to keyboard appearance or orientation change
Parent widget recreated its child
An InheritedWidget the widget depends on (Class.of(context) pattern) change
这意味着build方法不应触发http调用或修改任何状态。
这与问题有什么关系?
您面临的问题是您的构建方法具有副作用/不纯正,从而使多余的构建调用变得很麻烦。
您应该使构建方法纯净,而不是阻止构建调用,以便可以在没有影响的情况下随时调用它。
在您的示例中,您将小部件转换为StatefulWidget,然后将该HTTP调用提取到您所在州的initState:
ChangeNotifierProvider(
create: (_) => UserService(),
),
答案 1 :(得分:2)
您不应使用ChangeNotifierProvider.value
。而是使用默认构造函数:
ChangeNotifierProvider(
builder: (_) => UserService(),
)
否则,您的构建方法不纯,您将遇到How to deal with unwanted widget build?
中所述的问题