Flutter Provider 监听提供者中的条件

Flutter Provider Listen to a condition within 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

创建一个名为 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;

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

编辑:

@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

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

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,
    );

您可以使用第二层 class。

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")                        
                    );
                },
            ),
        );
    }
}