【问题标题】:ProxyProvider - how to call proxy from its sub-providers?ProxyProvider - 如何从其子提供者调用代理?
【发布时间】:2021-12-07 15:30:15
【问题描述】:

从其“子”提供者调用(并将值传递给)ProxyProvider 的正确方法是什么? 目前我将回调函数作为参数传递给“子”提供者,将其存储为函数,然后我可以在需要时调用它。 它的工作原理是调用了 ProxyProvider(并传递了值),但同时它破坏了 notifyListeners(),它被称为下一个 - 尽管消费者在“子”提供者中搜索 getter(并且找不到它)仅用于 ProxyProvider。

这是我收到的错误:

错误:org-dartlang-debug:synthetic_debug_expression:1:1:错误: 没有为“AudioModel”类定义 getter 'audInd'。

  • “AudioModel”来自“package:quiz_game_new/models/audioModel.dart”(“lib/models/audioModel.dart”)。尝试将名称更正为 一个现有的 getter,或定义一个名为 'audInd' 的 getter 或字段。 听得见^^^^^^

代码

提供者(audioModel.dart):

class AudioModel extends ChangeNotifier {
    int _audioIndex = -1;
    Function? audioIndexChanged;
      
    void setCallbacks(Function _audioPlaybackCompleted, Function _audioIndexChanged) {
        audioPlaybackCompleted = _audioPlaybackCompleted;
        audioIndexChanged = _audioIndexChanged;
    }
    
    //Some code that changes _audioIndex and afterwards calls audioIndexChanged!(_audioIndex)
}

ProxyProvider (commonModel.dart)

class CommonModel extends ChangeNotifier {
    CommonModel(this.audioModel);
    final AudioModel audioModel;
    
    int _audioIndex = -1;
    int get audioIndex => _audioIndex;
    
    void setCallbacksForAudioPlayback() {
        audioModel.setCallbacks(audioPlaybackCompleted, audioIndexChanged);
    }

    void audioIndexChanged(int audInd) {
        _audioIndex = audInd;
        notifyListeners();
    }
}

初始化:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider<STTModel>(create: (context) => STTModel()),
          ChangeNotifierProvider<QuestionModel>(
              create: (context) => QuestionModel()),
          ChangeNotifierProvider<AudioModel>(create: (context) => AudioModel()),
          ChangeNotifierProxyProvider3<STTModel, QuestionModel, AudioModel,
                  CommonModel>(
              create: (BuildContext context) => CommonModel(
                  Provider.of<STTModel>(context, listen: false),
                  Provider.of<QuestionModel>(context, listen: false),
                  Provider.of<AudioModel>(context, listen: false)),
              update:
                  (context, sttModel, questionModel, audioModel, commonModel) =>
                      CommonModel(sttModel, questionModel, audioModel))
        ],
        child: MaterialApp(
            title: 'Flutter Demo',
            initialRoute: '/',
            routes: {
              '/': (context) => ScreenMainMenu(),
              '/game': (context) => ScreenGame(),
            }));
  }
}

【问题讨论】:

  • 你能说明你是如何初始化这些提供者的吗?
  • 好的,添加到问题描述的末尾
  • 您是否尝试过在update 中直接返回commonModel 而不是创建一个新的?我认为没有必要在您的场景中创建一个新实例。此外,如果您想更新CommonModel,最好在CommonModel 中有一个函数来处理要更新的属性。 (例如commonModel.updateSomething(...); return commonModel;

标签: flutter dart proxy provider flutter-provider


【解决方案1】:

什么是正确的调用方式(并将值传递给) ProxyProvider 来自其“子”提供者?

我不是“嵌套”提供程序的忠实拥护者:它经常导致此类问题并且不会降低可读性。
在我的项目中,我通常为每个功能使用一个提供者,我在尽可能低的级别声明和使用它。 在你的情况下,我想我会使用你的 STTModelQuestionModelAudioModel 并且会忘记 CommonModel 的想法(我猜唯一的工作就是合并你所有的提供者?) .

你仍然可以保持你的逻辑,但你应该考虑以下几点:

在您的AudioModel 类中,更新_audioIndex 所在的方法并添加notifyListeners()

class AudioModel extends ChangeNotifier {
  //...
  int get audioIndex => _audioIndex;

  void updateIndex(int index) {
    _audioIndex = index; 
    //The rest of your code
    notifyListeners();
  } 

  //...
}

您的 Providers 的创建看起来没问题,但请考虑更新您的 ChangeNotifierProxyProviderupdate 方法以获取类似的内容:

update: (_, sttModel, questionModel, audioModel) => 
commonModel!..update(sttModel, questionModel, audioModel),

在您的 CommonModel 中

 void update(SttModel sttModelUpdate, QuestionModel questionModelUpdate, AudioModel audioModelUpdate) {
    audioModel = audioModelUpdate;
    questionModel = questionModelUpdate;
    sttModel = sttModelUpdate;
    
    //Retrieve the index here from your audioModel
    _audioIndex = audioModel.audioIndex;

    notifyListeners();
  }

这样,每当您在 AudioModel 类中调用 updateIndex 方法时,notifyListeners() 将更新 CommonModel 并且您将拥有最新的 _audioIndex
然后它应该可以正常工作了,不再需要你的回调方法了!

【讨论】:

  • - 我想我只是使用了您的 STTModel、QuestionModel 和 AudioModel,并且会忘记 CommonModel 的想法(我猜唯一的工作就是合并您的所有提供者?)。嗯,但是通过这样的设置,你将如何覆盖动作链接?我以前尝试过这种方法,但我很快就卡住了。这些模型中发生了什么: 1. QuestionModel 从 API 获取带有音频文件的 URL。完成后,然后 2.AudioModel 播放在步骤 1 中收到的音频文件。完成后,然后 3.STTModel 听您的声音并等待输入
  • 抱歉,这里仍然习惯于如何格式化 cmets... 您如何将此类操作与仅状态链接起来?每个步骤都有一个监听器,在某些时候应该在不同的模型上执行一些方法。使用 CommonModel(代理提供者)它有点工作,只是将 CommonModel 方法作为回调传递给子提供者似乎有点奇怪。
  • 您的问题看起来比您在最初的问题中写下的要复杂得多,我需要更多的时间和信息来定义哪种合适的架构最适合您的情况。如果您的 AudioModel 依赖于 QuestionModel,那么 AudioModel 也应该定义为 ChangeNotifierProxyProvider 并在检索到新 URL 时更新。
  • 嗯,这就是为什么我在中间有 CommonModel - 我用它来传递所有 3 个模型的数据,在这些模型中处理数据,然后发送回 CommonModel(不仅是数据,还有回调)。如果我没记错的话,那么如果从所有这 3 个模型中我只是将数据传递给 CommonModel 并且不从它们调用 notifyListeners() ,但仅在 CommonModel 中,那么这 3 个模型也可能只是常规类,不需要让他们成为 ChangeNotifier,对吧?但是它仍然没有回答我最初的问题 - 有没有更好的方法从它使用的类中调用 CommonModel (proxyProvider)?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
  • 2012-12-18
相关资源
最近更新 更多