无法使用 Provider.of(context) 调用类方法

Posted

技术标签:

【中文标题】无法使用 Provider.of(context) 调用类方法【英文标题】:Not able to call class method using Provider.of(context) 【发布时间】:2020-09-18 21:41:30 【问题描述】:

我正在学习使用此代码使用状态管理和提供程序包。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

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

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider<Data>(
      create: (context) => Data(),
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: MyText(),
          ),
          body: Level1(),
        ),
      ),
    );
  


class Level1 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Container(
      child: Level2(),
    );
  


class Level2 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Column(
      children: <Widget>[
        MyTextField(),
        Level3(),
      ],
    );
  


class Level3 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Text(Provider.of<Data>(context).data);
  


class MyText extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Text(Provider.of<Data>(context).data);
  


class MyTextField extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return TextField(
      onChanged: (newText) 
        print("onChanged Start");
        Provider.of<Data>(context).changeString(newText); //this line troubling me
        print("onChanged End");
      ,
    );
  


class Data extends ChangeNotifier 
  String data = "Some Data";

  void changeString(String newString) 
    print("changeString Start");
    print(newString + " changeString Text");
    data = newString;
    notifyListeners();
    print("changeString End");
  

在运行应用程序时,AppBar Text MyText() 和 Level 3 Text Text() 工作正常。 好像我在代码中更改了data 的值并热重启了data 中更新的更改,并且也反映在了应用程序中。

我还创建了MyTextFiled(),如果发生任何更改,它应该在data 中更新,但changeString() 方法没有被第64 行的Provider.of&lt;Data&gt;(context) 调用。

这是我在 TextField 中键入“Test”时的控制台输出。

onChange Start
t
onChange Start
te
onChange Start
tes
onChange Start
test

预期是:

onChange Start
t
changeString Start
t changeString Text
changeString End
onChange End
(so on .....)

我正在使用provider: ^4.1.2,在教程(我正在关注的)中,他们使用provider: ^3.0.0+1 所以,我在第 10 行将builder 更改为create,因为它显示错误。

我的 Flutter 版本:

Flutter 1.17.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision e6b34c2b5c (4 weeks ago) • 2020-05-02 11:39:18 -0700
Engine • revision 540786dd51
Tools • Dart 2.8.1

PS:借助此示例Provider Example 将Provider.of&lt;Data&gt;(context).changeString(newText); 替换为context.read&lt;Data&gt;().changeString(newText);,我的问题得到解决

但我无法理解为什么 Provider.of(context) 不起作用但 context.read() 起作用。 请给我解释一下。

对于在这个神圣的社区提出一个愚蠢的问题,我深表歉意。 感谢您仔细聆听/阅读我的问题。

【问题讨论】:

【参考方案1】:

像这样更改 TextField 的 onChanged 函数:

class MyTextField extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return TextField(
      onChanged: (newText) 
        print("onChanged Start");
        Provider.of<Data>(context,listen:false).changeString(newText); //notice , listen default value is true
        print("onChanged End");
      ,
    );
  


context.read&lt;Data&gt;() 是对的,但你应该知道 context.read&lt;T&gt;() 等同于 Provider.of&lt;T&gt;(context,listen:false)

正如documentation中提到的那样=>

context.watch&lt;T&gt;()Provider.of&lt;T&gt;(context)Provider.of&lt;T&gt;(context,listen:true) 相同,因为默认情况下 listen 为 true context.read&lt;T&gt;() 等同于Provider.of&lt;T&gt;(context,listen:false)

【讨论】:

以上是关于无法使用 Provider.of(context) 调用类方法的主要内容,如果未能解决你的问题,请参考以下文章

Provider.of(context, listen: false) 是不是等同于 context.read()?

Flutter Provider:为啥在调用 Provider.of<Widget>(context) 时会出现此错误,如 tihis:

如何将 get_it 用于 Provider.of<ExampleProvider>(context)?

在dispose()方法内部调用带有Provider.of(context)的方法会导致“查找已停用的小部件的祖先是不安全的。”

Flutter之跨组件状态共享Provider剖析

Flutter之跨组件状态共享Provider剖析