Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dart 颤振以编程方式触发FutureBuilder_Dart_Flutter - Fatal编程技术网

Dart 颤振以编程方式触发FutureBuilder

Dart 颤振以编程方式触发FutureBuilder,dart,flutter,Dart,Flutter,假设我有这样的东西: return FutureBuilder( future: _loadingDeals, builder: (BuildContext context, AsyncSnapshot snapshot) { return RefreshIndicator( onRefresh: _handleRefresh, ... ) } ) 在\u handleRefresh方法中,我希望以编程方式触发FutureBuilder

假设我有这样的东西:

return FutureBuilder(
  future: _loadingDeals,
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    return RefreshIndicator(
      onRefresh: _handleRefresh,
        ...
    )
  }
 )
\u handleRefresh
方法中,我希望以编程方式触发FutureBuilder的重新运行

有这样的事吗

用例:

当用户拉下
刷新指示器
,则
\u手柄刷新
只会使
FutureBuilder
重新运行

编辑

完整的代码段端到端,没有刷新部分。我已经切换到使用
StreamBuilder
,那么
refreshIndicator
部分将如何适应所有这一切

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']),
                    );
                },
              ),
        }
      },
    );
  }
}
类DealList扩展了StatefulWidget{
@凌驾
State createState()=>new_DealList();
}
类_DealList使用AutomaticEpaLiveClientMixin扩展状态{
//防止切换到时刷新选项卡
//为什么??https://stackoverflow.com/q/51224420/1757321
bool get wantKeepAlive=>true;
最终RestDatasource api=新RestDatasource();
字符串标记;
StreamController\u dealsController;
@凌驾
void initState(){
super.initState();
_dealsController=新的StreamController();
_loadingDeals();
}
_loadingDeals()异步{
SharedReferences prefs=等待SharedReferences.getInstance();
this.token=prefs.getString('token');
最终结果=
this.api.checkInterests(this.token).then((interestResponse)异步{
_dealsController.add(利息响应);
利息回报率;
});
返回res;
}
_handleRefresh(数据)异步{
SharedReferences prefs=等待SharedReferences.getInstance();
final token=prefs.getString('token');
等待这个.api.checkInterests(令牌)。然后((interestResponse){
_dealsController.add(利息响应);
});
返回null;
}
@凌驾
小部件构建(构建上下文){
super.build(context);//DealsDetailPage(
交易详情:交易,
),
),
);
},
标题:文本(交易['name']),
字幕:文本(交易['expires']),
);
},
),
}
},
);
}
}

为什么不使用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),
            ...
        )
      }
    );
  }
}
class\u YourWidgetState扩展状态{
StreamController\u刷新控制器;
...
initState(){
超级的。。。
_refreshController=新的StreamController();
_loadingDeals();
}
_loadingDeals(){
_刷新控制器。添加(“”);
}
_handleRefresh(数据){
如(x)项加上(“”);
}
...
构建(上下文){
...
返回流生成器(
流:_refreshController.stream,
生成器:(BuildContext上下文,异步快照){
返回刷新指示器(
onRefresh:_handleRefresh(snapshot.data),
...
)
}
);
}
}

我使用StreamBuilder创建了一个flatter主示例的要点,

使用StreamBuilder是一个解决方案,但是,要以编程方式触发FutureBuilder,只需调用setState,它将重建小部件

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

与StreamBuilder相比,我更喜欢FutureBuilder,因为我在使用Firestore进行我的项目,并且您会收到reads的账单,所以我的解决方案就是这样

    _future??= getMyFuture();

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

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

OK。这是下一级代码:p。我会深呼吸,细细咀嚼。会让你知道事情的进展。看起来是这样,但事实并非如此!尝试一下,你会发现它是有效的。我使用StreamBuilder创建了一个关于颤振主示例的要点,请检查:在上面的示例中,您将
快照.data
发送回
\u handleRefresh
方法。为什么?在
\u handleRefresh
中,如果(x)什么是
x
snapshot.data
:如果不需要,不需要传递它<代码>如果(x)是必须触发刷新的条件。如果没有条件,您可以删除
if
并调用
\u refreshController。立即添加(“”
。您想要的不是@Feu所述的
Future
,而是
Stream
。为什么不直接使用
setState
?@JonahWilliams我正在使用
setState
,但它不起作用。这可能是因为我正在使用AutomaticKepaLiveClientMixin的
,所以整个小部件不会在状态更改时重建。为什么?请看这里: