微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Flutter-在FutureBuilder中使用RefreshIndicator拉动刷新

如何解决Flutter-在FutureBuilder中使用RefreshIndicator拉动刷新

编辑:Minimal reproducible example。请查看main.dart中的refresh-Method。

我正在使用FutureBuilder显示网络请求的结果。我在initstate调用提取方法(如建议的here):

Future<List<CheckIn>> futureCheckIn;

@override
void initState() {
  super.initState();
  _eventArg = Provider.of<EventArg>(context,listen: false);

  _helper = ApiHelper(context);
  futureCheckIn = _helper.fetchCheckIns(_eventArg.getEvent().id.toString());
}

我现在想使用Refreshindicator来允许用户刷新屏幕。 在我的网络请求以异常结束(例如404)之前,这非常有效。通常,该异常会被FutureBuilder捕获,但是在执行Refreshindicator中的请求后,该异常将无法处理...

这是我的代码

Refreshindicator buildresult(List<CheckIn> checkIns,BuildContext context) {
return Refreshindicator(
  key: _refreshKey,onRefresh: () async {
    setState(() {});
    futureCheckIn =
        _helper.fetchCheckIns(_eventArg.getEvent().id.toString()); // this Could end with an exception
  },child: Container(
    height: MediaQuery.of(context).size.height,child: SingleChildScrollView(
      physics: AlwaysScrollableScrollPhysics(),scrollDirection: Axis.vertical,child: Column(
        children: [
          Container(
            margin: EdgeInsets.all(10),child: Text(
              constants.CHECK_IN_SCREEN_DESCRIPTION,style: TextStyle(fontSize: 16),textAlign: TextAlign.justify,),ListView(
            physics: NeverScrollableScrollPhysics(),padding: EdgeInsets.fromLTRB(10,10,0),shrinkWrap: true,children: checkIns.map((el) {
              return Card(
                elevation: 4,child: ListTile(
                  title: Text(el.name),onTap: () async {
                   ...
                  },trailing: Column(
                    mainAxisAlignment: MainAxisAlignment.center,children: [
                      Icon(
                        Icons.arrow_forward_ios,color: Colors.black,)
                    ],);
            }).toList(),)
        ],);

}

如何将RefreshindicatorFutureBuilder一起正确使用?

编辑@Shri Hari:抛出此异常

class AppException implements Exception {
 final _message;
 final _prefix;

 AppException([this._message,this._prefix]);

 String toString() {
   return "$_prefix$_message";
 }
}

class NotFoundException extends AppException {
  NotFoundException([String message]) : super(message,"Data not found: ");
}

enter image description here

编辑@Mhark Ba​​toctoy:是的,它是FutureBuilder的一部分:

@override
Widget build(BuildContext context) {
return FutureBuilder(
  future: futureCheckIn,builder: (context,snapshot) {
    if (snapshot.hasData) {
      List<CheckIn> checkIns = snapshot.data;

      return buildresult(checkIns,context); // Refreshindicator is nested in here
    } else if (snapshot.hasError) {
      // Error handling
      ... 
    }

    // Spinner während der Datenabfrage
    return Center(
      child: CircularProgressIndicator(),);
  },);

很不幸地将onRefresh-方法从更改为

 onRefresh: () async {
  setState(() {});
  futureCheckIn =
    _helper.fetchCheckIns(_eventArg.getEvent().id.toString()); // this Could end with an exception
  },

onRefresh: () async {
  setState(() {});
  return futureCheckIn =
    _helper.fetchCheckIns(_eventArg.getEvent().id.toString()); // this Could end with an exception
  },

onRefresh: () async {
  setState(() {});
  return _helper.fetchCheckIns(_eventArg.getEvent().id.toString()); // this Could end with an exception
  },

不会更改错误...

解决方法

不确定这是否是最佳答案,但我遇到了同样的问题,必须继续前进。所以,这就是我学到的和做的。

RefreshIndicator 不喜欢例外。即使在将它们移到 try / catchonError 下并成功消费异常之后,RefreshIndicator 仍然为未处理的异常而哭泣(有点奇怪,但我将不得不对其进行更多调查)。

我所做的是确保我的 API 调用不会引发任何异常。这意味着,API 调用本身(在本例中为 fetchCheckIns() 函数调用)捕获所有类型的已知/未知异常 [ catch (e) ] 并在您从 API 返回的响应对象中设置一个标志(在本例中为 fetchCheckIns() 的返回类型对象)。

现在,在您的 FutureBuilder 中,当您调用 buildResult(checkIns,context) 时,检查 snapshot.data 并查找任何失败标志。如果失败,请以不同的方式渲染屏幕。即:

    if (snapshot.hasData) {
      if (snapshot.data.error == true) {
         return ...; // Render error message
      } else {
         return buildResult(snapshot.data,context);
      }
    }

这也意味着,您可能无法返回对象列表,并且可能必须将其包装在包含对象列表的单个对象中。

意味着,您的 CheckIn 对象可能被类似

class AllCheckIn {
   List<CheckIn> checkIns;
   bool error;
   String errorMsg;
}

或者,您还可以根据您在 API 调用中收到和捕获的异常添加更多错误消息说明,并在您的 FutureBuilder 中使用它。

希望对您有所帮助。

,
 _helper.fetchCheckIns(_eventArg.getEvent().id.toString()); 

它返回一个Future。您需要一个data或一个error。您可以在async await块内使用try catch finally,也可以使用Future.then() / Future.catchError / Future.whenComplete()

示例:

onRefresh: () async {
try {
   //You can use the await keyword here.
   return futureCheckIn =
    await _helper.fetchCheckIns(_eventArg.getEvent().id.toString());
}catch (err){
  //You can display the error here using a snackbar.
  }finally {
    //This executes whether there is an error or not. 
 }

},

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。