Flutter Provider收听提供商内部的情况

时间:2020-10-18 11:56:14

标签: flutter flutter-provider

我有一个提供州的提供商:

enum RemoteJSONState { parsing, parsed, failedToParse }

在我的一个小部件中,我听所有的更改

class RemoteJSONStateProvider with ChangeNotifier {
  set remoteJSONState(RemoteJSONState givenState) {
    if (givenState == _remoteJSONState) {
      return;
    }

    _remoteJSONState = givenState;
    notifyListeners();
  }
}

在我的另一个小部件中,我只想听“已解析”状态。这是因为最初我的小部件正在基于本地存储运行信息。当获取远程数据时,它将使用获取的信息进行更新。如果获取失败,我只是不想构建我的小部件,而是想使用可用的本地信息。因此,我不想重建小部件。

这是我到目前为止尝试过的。

@override
  Widget build(BuildContext context) {
    RemoteJSONStateProvider =
        Provider.of<RemoteJSONStateProvider>(context);
  }

问题是,如果RemoteJSONStateProvider状态更改为“ failedToParse”,我的窗口小部件将得到重建。我怎么只能听一个条件?

RemoteJSONStateProvider._remoteJSONState == RemoteJSONState.parsed

4 个答案:

答案 0 :(得分:1)

您可以使用第二层类。

enum RemoteJSONState { parsing, parsed, failedToParse }

class RemoteJSONStateProvider extends ChangeNotifier {
    
    RemoteJSONState _jsonState;
    RemoteJSONState get jsonState => _jsonState; 
    
    RemoteJSONStateProvider();
    RemoteJSONStateProvider.instance();

    remoteJSONState(RemoteJSONState givenState) {
        if (givenState == _remoteJSONState) {
            return;
        }
        _jsonState = givenState;
        notifyListeners();
    }
}


class MyNotifier extends ChangeNotifier {
   RemoteJSONStateProvider _jsonStateProvider;
   RemoteJSONState _jsonState;
   RemoteJSONState get jsonState => _jsonState;
   VoidCallback _jsonStatusListener;

   MyNotifier();
   MyNotifier.instance(BuildContext context){
      _listenJSONState(context);
   }

   _listenJSONState(BuildContext context){
      _jsonStateProvider = Provider.of<RemoteJSONStateProvider>(context, listen: false);
      _jsonStatusListener = (){
         if(_jsonStateProvider.jsonState == RemoteJSONState.parsed){
            _jsonState == RemoteJSONState.parsed;
            notifyListeners();
         }
      };
      _jsonStateProvider.addListener(_jsonStatusListener);
   }

   parseJSON(RemoteJSONState state){
       _jsonStateProvider.remoteJSONState(state);
   }
}

class YourWidget extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return ChangeNotifierProvider(
        create: (context) => MyNotifier.instance(context),
            child: Consumer<MyNotifier>(
                builder: (context, myNotifierModel, child) {
                    return myNotifierModel.jsonState == null 
                    ? FlatButton(
                        child: Text("parse json"),
                        onPressed: (){
                            myNotifierModel.parseJSON(RemoteJSONState.parsed);
                        }
                    )
                    : Container(
                        child: myNotifierModel.jsonState == RemoteJSONState.parsing ?
                        Text("JSON PARSING") : 
                        Text("JSON PARSED")                        
                    );
                },
            ),
        );
    }
}

答案 1 :(得分:0)

创建一个名为isParsedStateChange的局部变量,该局部变量仅在调用已解析状态时通知。

class RemoteJSONStateProvider with ChangeNotifier {
  bool _isParsedStateChange = false;
  get isParsedStateChange => _isParsedStateChange;

  set parsedJSONState(RemoteJSONState givenState) {
    _isParsedStateChange = (RemoteJSONState. parsed == givenState) 
    if(_isParsedStateChange) {
      notifyListeners();
     }
  }
}

使用方式

RemoteJSONStateProvider =
        Provider.of<RemoteJSONStateProvider>(context).isParsedStateChange;

注意:创建一个单独的方法来设置解析状态

答案 2 :(得分:0)

编辑:

@ jitsm555比我快8秒,代码更好。


您可以在提供程序中定义另一个变量,如下所示:

    bool isParsed = false;

并根据您的条件进行设置:

  class RemoteJSONStateProvider with ChangeNotifier {
    set remoteJSONState(RemoteJSONState givenState) {
      if (givenState == _remoteJSONState) {
        isParsed = true;
        return;
      }

      _remoteJSONState = givenState;
      notifyListeners();
    }
  }

在那之后,您只能收听isParsed条件:

   RemoteJSONStateProvider.isParsed

答案 3 :(得分:0)

其他答案使我不满意,因为我需要保留其他小部件的旧功能。经过一个小时的研究,我制作了一个Selector小部件来满足我的需求。

Selector<RemoteJSONStateProvider, RemoteJSONState>(
      builder: (context, remoteJSONStateProvider, child) {
        print("rebuild");
        return Text('build');
      },
      selector: (buildContext, remoteJSONStateProvider) =>
          remoteJSONStateProvider.remoteJSONState,
      shouldRebuild: (prev, next) =>
          prev != RemoteJSONState.parsed && next == RemoteJSONState.parsed,
    );