【问题标题】:Flutter Widget not updating when notifylisters is called调用通知列表时 Flutter Widget 未更新
【发布时间】:2021-06-03 11:52:50
【问题描述】:

我有一个 ChangeNotifier 正在从 Firebase Firestore 正确获取数据。但是,加载此数据时,我的 StatefulWidget 并未更新。我在这里做错了什么?

class MyViewModel with ChangeNotifier {
  MyViewModel();

  MyModel _myModel;
  FirebaseRepository _firebaseRepository = FirebaseRepository();

  void loadData(String userId) async {
    _myModel =
        await _firebaseRepository.getData(userId);

    notifyListeners();
  }

  getModelName(){
     return _myModel.name;
  }
}

还有一个 ChangeNotifierProvider 设置在我的小部件树的顶层

void main() => runApp(MyApp());


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider(
            create: (context) => MyViewModel(),
          ),
        ],
        child: MaterialApp(
            home: HomeWithBottomNav(title: 'Bottom Nav Home Page'),
            routes: <String, WidgetBuilder>{
              // define the routes
             
              MyPage.routeName: (BuildContext context) => MyPage(),
              
            }));
  }
}

还有一个 StatefulWidget 正在尝试监听数据

class MyPage extends StatefulWidget {
  static const String routeName = "/myPage";

  @override
  _State createState() => _State();
}

class _State extends State<MyPage> {
  MyViewModel myViewModel =
      new MyViewModel();

  @override
  void initState() {
    myViewModel.loadData('userId');
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    Provider.of<MyViewModel>(context);

    return Consumer<MyViewModel>(
      builder: (context, myViewModel, child) {
        AppBar appBar = AppBar(
            title: Text("Model Name: $myViewModel.getModelName()"), // This is not getting the data fetched from firestore
        );

        SingleChildScrollView singleChildScrollView = SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[],
          ),
        );

        Scaffold scaffold =
            Scaffold(appBar: appBar, body: singleChildScrollView);

        return scaffold;
      },
    );
  }
}


【问题讨论】:

    标签: flutter google-cloud-firestore flutter-provider


    【解决方案1】:

    我认为问题在于两个实例,一个提供状态更改,即您的视图注册为侦听器的一个,而不是您调用loadData on 的那个。

    这应该可行:

    @override
      void initState() {
        WidgetsBinding.instance.addPostFrameCallback((_) async { 
          await Provider.of<MyViewModel>(context, listen: false).loadData('userId');
        });
        super.initState();
      } 
    

    您不能直接在 initState 方法内调用异步方法,但您可以注册一个异步回调,以便在安装 Page 小部件后执行,因此是 addPostFrameCallback。而且因为它是异步的,所以您也可以访问 BuildContext。

    【讨论】:

      【解决方案2】:

      我认为这是因为您有两个 MyViewModel 实例。一个在这里创建:

         ChangeNotifierProvider(
                  create: (context) => MyViewModel(),
                ),
      

      这里还有一个:

      class _State extends State<MyPage> {
        MyViewModel myViewModel =
            new MyViewModel();
      

      您调用 loadData 函数的是第二个,但您从消费者那里获得访问权的是第一个。 我建议您将有状态小部件更改为无状态小部件,在第二次实例化 MyViewModel 时删除,而不是从 initsatate 调用所需的函数,而是从 MyViewModel 的构造函数中调用它。 我希望这会有所帮助

      【讨论】:

        【解决方案3】:

        你应该这样调用myViewModel:

        Provider.of<myViewModel>(context,listen:false).loadData('userId');
        

        但默认情况下,您不能在 initstate 中调用它,因为我们在那里没有上下文

        【讨论】:

          猜你喜欢
          • 2021-12-23
          • 2021-05-18
          • 1970-01-01
          • 2022-10-14
          • 2023-04-09
          • 1970-01-01
          • 1970-01-01
          • 2021-12-20
          • 2021-04-23
          相关资源
          最近更新 更多