【问题标题】:flutter: State is lost on Hot Reload when using Provider颤振:使用提供程序时,状态在热重载时丢失
【发布时间】:2019-10-28 01:50:47
【问题描述】:

我正在使用 Provider 来管理我的应用程序的状态。以下是我的实现方式。

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,我认为这意味着状态是丢失。我怎样才能克服同样的问题?我做错了吗?

【问题讨论】:

    标签: flutter dart flutter-dependencies


    【解决方案1】:

    您不应使用ChangeNotifierProvider.value。而是使用默认构造函数:

    ChangeNotifierProvider(
      builder: (_) => UserService(),
    )
    

    否则,您的构建方法不纯,您将遇到How to deal with unwanted widget build? 中所述的问题

    【讨论】:

    • 我看到很多例子都说 UserService() 而不是对象 userService。它必须是一个新实例化的对象吗?因为我不知道如何将它与新设置的值一起使用。
    • @chitgoks 如文档所述,如果您已经有一个对象实例,则可以使用ChangeNotifierProvider.value
    • 我改用了 ProxyProvider。因为我的变量属性发生了变化。
    • 我遇到了完全相同的问题,即使在 4.0.4 上使用 create: (_) =&gt; UserService(), 也是如此
    • @RémiRousselet 你太棒了。按照您的链接。我知道如果您执行路线,提供者也会失去状态。在 notifyListener() 之前。
    【解决方案2】:

    构建方法的设计方式应该是纯的/没有副作用。这是因为许多外部因素都可以触发新的小部件构建,例如:

    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
    

    这意味着构建方法不应触发 http 调用或修改任何状态。

    这与问题有什么关系?

    您面临的问题是您的构建方法有副作用/不纯,使得无关的构建调用很麻烦。

    您应该使您的构建方法纯粹,而不是阻止构建调用,以便可以随时调用它而不会受到影响。

    在您的示例中,您需要将小部件转换为 StatefulWidget,然后将该 HTTP 调用提取到您的 State 的 initState:

    ChangeNotifierProvider(
        create: (_) => UserService(),
    ),
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-22
      • 2019-12-17
      • 2019-05-31
      • 2018-09-26
      • 2020-10-26
      • 2020-02-10
      • 2020-02-01
      • 1970-01-01
      相关资源
      最近更新 更多