【问题标题】:Flutter Programmatically trigger FutureBuilderFlutter 以编程方式触发 FutureBuilder
【发布时间】:2018-08-02 23:22:21
【问题描述】:

假设我有这样的事情:

return FutureBuilder(
  future: _loadingDeals,
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    return RefreshIndicator(
      onRefresh: _handleRefresh,
        ...
    )
  }
 )

_handleRefresh 方法中,我想以编程方式触发FutureBuilder 的重新运行。

有这种事吗?

用例:

当用户拉下refreshIndicator 时,_handleRefresh 只会让FutureBuilder 重新运行。

编辑

完整的代码 sn-p 端到端,没有刷新部分。我已经改用StreamBuilderrefreshIndicator 部分如何适应所有这些?

class DealList extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _DealList();
}

class _DealList extends State<DealList> with AutomaticKeepAliveClientMixin {
  // prevents refreshing of tab when switch to
  // Why? https://stackoverflow.com/q/51224420/1757321
  bool get wantKeepAlive => true; 

  final RestDatasource api = new RestDatasource();
  String token;
  StreamController _dealsController;

  @override
  void initState() {
    super.initState();
    _dealsController = new StreamController();
    _loadingDeals();
  }

  _loadingDeals() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    this.token = prefs.getString('token');

    final res =
        this.api.checkInterests(this.token).then((interestResponse) async {
      _dealsController.add(interestResponse);
      return interestResponse;
    });
    return res;
  }

  _handleRefresh(data) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    final token = prefs.getString('token');
    await this.api.checkInterests(token).then((interestResponse) {
      _dealsController.add(interestResponse);
    });
    return null;
  }

  @override
  Widget build(BuildContext context) {
    super.build(context); // <-- this is with the wantKeepAlive thing
    return StreamBuilder(
      stream: _dealsController.stream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {

        if (snapshot.hasError) {
          ...
        }

        if (snapshot.connectionState != ConnectionState.done) {
          return Center(
            child: CircularProgressIndicator(),
          );
        }

        if (!snapshot.hasData &&
            snapshot.connectionState == ConnectionState.done) {
          return Text('No deals');
        }

        if (snapshot.hasData) {
          return ListView.builder(
                physics: const AlwaysScrollableScrollPhysics(),
                itemCount: snapshot.data['deals'].length,
                itemBuilder: (context, index) {
                  final Map deal = snapshot.data['deals'][index];
                  return ListTile(
                      onTap: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) => DealsDetailPage(
                                  dealDetail: deal,
                                ),
                          ),
                        );
                      },
                      title: Text(deal['name']),
                      subtitle: Text(deal['expires']),
                    );
                },
              ),
        }
      },
    );
  }
}

【问题讨论】:

  • @Feu 所述,您想要的是 Stream,而不是 Future
  • 为什么不直接使用setState
  • @JonahWilliams 我目前正在使用setState,但它不起作用。那可能是因为我使用的是with AutomaticKeepAliveClientMixin,所以整个小部件不会在状态更改时重建。为什么?请看这里:stackoverflow.com/questions/51224420/…

标签: dart flutter


【解决方案1】:

为什么不使用 StreamBuilder 和 Stream 而不是 FutureBuilder?

类似的...

class _YourWidgetState extends State<YourWidget> {
  StreamController<String> _refreshController;

  ...
  initState() {
    super...
    _refreshController = new StreamController<String>();
   _loadingDeals();
  }

  _loadingDeals() {
    _refreshController.add("");
  }

  _handleRefresh(data) {
    if (x) _refreshController.add("");
  }

  ...
  build(context) {
    ...
    return StreamBuilder(
      stream: _refreshController.stream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return RefreshIndicator(
          onRefresh: _handleRefresh(snapshot.data),
            ...
        )
      }
    );
  }
}

我使用 StreamBuilder 创建了一个带有 Flutter 主要示例的 Gist,check it out

【讨论】:

  • 好的。那是那里的一些下一级代码:p。会深呼吸并咀嚼它。会告诉你进展如何。
  • 看起来是这样,但事实并非如此!试试看,你会发现它有效。
  • 我使用 StreamBuilder 创建了一个带有 Flutter 主要示例的 Gist,请查看:gist.github.com/ffeu/e77664dd322089649d9b6f0f8fb04d42
  • 在上面的示例中,您将snapshot.data 发送回_handleRefresh 方法。为什么?而在_handleRefreshif (x) ..x是什么?
  • snapshot.data: 如果你不需要它,你不需要传递它。 if (x) .. 是触发刷新的条件。如果没有条件,您可以删除if并立即致电_refreshController.add("")
【解决方案2】:

使用 StreamBuilder 是一种解决方案,但是,要以编程方式触发 FutureBuilder,只需调用 setState,它就会重建 Widget。

return RefreshIndicator(
  onRefresh: () {
          setState(() {});
        },
    ...
)

【讨论】:

    【解决方案3】:

    我更喜欢 FutureBuilder 而不是 StreamBuilder,因为我将 Firestore 用于我的项目,并且您通过读取来计费,所以我的解决方案是这样的

        _future??= getMyFuture();
    
        shouldReload(){
           setState(()=>_future = null)
        }
        
        FutureBuilder(
           future: _future, 
           builder: (context, snapshot){
        return Container();
        },
       )
     
    

    任何需要您获取新数据的用户活动只需调用 shouldReload()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-16
      • 1970-01-01
      • 1970-01-01
      • 2019-04-04
      • 1970-01-01
      • 1970-01-01
      • 2019-03-21
      • 1970-01-01
      相关资源
      最近更新 更多