颤动:使用提供程序时热重载状态丢失

时间:2019-06-13 12:53:27

标签: flutter dart flutter-dependencies

我正在使用提供程序来管理我的应用程序状态。这是我的实现方式。

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上调用的,我认为这意味着状态为丢失。我该如何克服呢?我在做错什么吗?

2 个答案:

答案 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?

中所述的问题