Flutter:带有初始网络请求的 ChangeNotifierProvider

Posted

技术标签:

【中文标题】Flutter:带有初始网络请求的 ChangeNotifierProvider【英文标题】:Flutter: ChangeNotifierProvider with an initial network request 【发布时间】:2019-12-20 01:56:57 【问题描述】:

我有一个代表电影列表的小部件,在我的模型中我有 getMovies() 函数,它从网络请求中检索电影列表:

enum MovieListState  IDLE, LOADING, ERROR 

class MovieListModel extends ChangeNotifier 
  MovieListModel(this._client);

  GatewayClient _client;

  MovieListState _viewState = MovieListState.LOADING;

  MovieListState get viewState => _viewState;

  set viewState(MovieListState value) 
    _viewState = value;
    notifyListeners();
  

  Future<List<Movie>> getMovies() async 
    try 
      viewState = MovieListState.LOADING;
      var movies = await _client.getMovies();
      viewState = MovieListState.IDLE;
      return movies;
     on KoException catch (e) 
      viewState = MovieListState.ERROR;
      throw e;
    
  

然后从小部件中我想根据请求的状态构建布局:

@override
  Widget build(BuildContext context) 
    state = Provider.of<AppState>(context);
    var model = MovieListModel(Provider.of<GatewayClient>(context));

    return ChangeNotifierProvider<MovieListModel>.value(
        value: model,
        child: Consumer<MovieListModel>(builder: (context, model, child) 
          if (model.viewState == MovieListState.IDLE) 
            return _getList(); // Method which generates the content with the retrieved values
           else if (model.viewState == MovieListState.LOADING) 
            return Center(
              child: CircularProgressIndicator(),
            );
           else 
            return Center(
              child: Text(_static.translate(context).movieListError),
            );
          
        ));
  

问题是,如何在小部件初始化的一开始就触发网络调用 getMovies()?我尝试在不同的点手动调用 getMovies() 方法,但我有一个错误,或者每次小部件调用其 build() 方法时调用都在重复。

提前致谢。

【问题讨论】:

【参考方案1】:

使用 FutureProvider 修复:

  @override
  Widget build(BuildContext context) 
    return FutureProvider<List<Movie>>.value(
      value: _model.getMovies(),
      initialData: List<Movie>(),
      catchError: (context, error) 
        return null;
      ,
      child: Consumer<List<Movie>>(
        builder: (context, data, widget) 
          // ...
        ,
      ),
    );
  

【讨论】:

对 getMovies() 的调用不应该在 initState() 中吗?因为如果您在 build() 方法中进行调用,那么对 UI 的任何更改都会触发 build 方法,从而导致不必要的 API 调用。 initState(),顾名思义,只被调用一次。可能不是这种情况下想要的行为。

以上是关于Flutter:带有初始网络请求的 ChangeNotifierProvider的主要内容,如果未能解决你的问题,请参考以下文章

flutter 网络请求dio的简单使用以及请求头参数的自定义

无法使用带有工作 api 的 http.get flutter 获取数据

Flutter 创建 API 请求并接收带有 - 'Ä' 'Ö' 'Ü' 'ß' 的字符串

Flutter 上传带有进度条的大文件。 App 和 Web 都支持

Flutter-網絡請求

flutter dio 网络请求问题