Flutter基础之Dart语言入门:Future异步使用

2022-04-11 17:58:37 浏览数 (1)

Flutter的开发离不开异步处理,dio是Flutter常用的第三方网络请求插件,这篇就带大家来了解下Flutter的异步和dio的使用

Dart类库有非常多的返回Future 或者 Stream 对象的函数,这些函数被称为异步函数,它们只会被设置好一些操作之后返回,如网络请求操作。

async await关键词支持异步编程

01

Future

用于处理异步操作,异步处理成功了就执行成功的操作,异步处理失败就捕获错误或者停止后续操作,一个Future只会对应一个结果,要么成功,要么失败。

Future的所有API的返回值仍然是一个Future对象,所以可以很方便的进行链式调用。

Future.then

模拟延时操作 then中接收异步结果并打印结果

代码语言:javascript复制
Future.delayed(new Duration(seconds: 2),(){
   return "hi world!";
}).then((data){
   print(data);
});
Future.catchError

如果异步任务发生错误,可以在catchError中捕获错误

代码语言:javascript复制
Future.delayed(new Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");
}).then((data){
   //执行成功会走到这里
   print("success");
}).catchError((e){
   //执行失败会走到这里
   print(e);
});

then 接收结果,catchError铺货异常,但并非只有catchError回调才能铺货错误,then方法还有一个可选参数onError,也可以铺货异常

Future.whenComplete

无论异步任务执行成功或失败都需要做一些事时, 1. 可以分别在 thencatchError中关闭以下对话框 2. 可以使用Future的whenComplete回调

代码语言:javascript复制
Future.delayed(new Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");
}).then((data){
   //执行成功会走到这里
   print(data);
}).catchError((e){
   //执行失败会走到这里
   print(e);
}).whenComplete((){
   //无论成功或失败都会走到这里
});
Future.wait

如果需要等待多个异步任务都执行结束后做某些操作,可以使用Future.wait,它接受一个Future数组参数, * 只有数组中所有的Future都执行成功后,才会触发then的成功回调, * 只要有一个Future执行失败,就会触发错误回调

代码语言:javascript复制
Future.wait([
  // 2秒后返回结果
  Future.delayed(new Duration(seconds: 2), () {
    return "hello";
  }),
  // 4秒后返回结果
  Future.delayed(new Duration(seconds: 4), () {
    return " world";
  })
]).then((results){
  print(results[0] results[1]);
}).catchError((e){
  print(e);
});

02

消除callback hell

使用async/await消除callback hell

代码语言:javascript复制
task() async {
   try{
    String id = await login("alice","******");
    String userInfo = await getUserInfo(id);
    await saveUserInfo(userInfo);
    //执行接下来的操作
   } catch(e){
    //错误处理
    print(e);
   }
}

async用来表示函数时异步,定义的函数会返回一个Future对象 await后面是一个Future,表示等待该异步任务完成,异步完成后才会往下走,await必须出现在async函数内部 async/await只是一个语法糖,编译器或解释器最终会将其转化为一个Promise(Future)的调用链。

03

Stream

Stream也是用于接收异步事件数据,和Future不同的是,它可以接收多个异步操作的结果(成功或失败),也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常,Stream常用于会多次读取数据的异步任务场景,如网络内容下载,文档读写等

代码语言:javascript复制
Stream.fromFutures([
  // 1秒后返回结果
  Future.delayed(new Duration(seconds: 1), () {
    return "hello 1";
  }),
  // 抛出一个异常
  Future.delayed(new Duration(seconds: 2),(){
    throw AssertionError("Error");
  }),
  // 3秒后返回结果
  Future.delayed(new Duration(seconds: 3), () {
    return "hello 3";
  })
]).listen((data){
   print(data);
}, onError: (e){
   print(e.message);
},onDone: (){

});

上面的代码依次输出

代码语言:javascript复制
I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3

04

网络请求 Future应用

异步最应用在网络请求,Flutter同样需要异步请求获取数据,dio是Flutter常用的网络请求插件,地址https://pub.dev/packages/dio。 同样项目中引入改插件,直接在pubspec.yaml文件中添加依赖

在使用的地方引入:

下面是项目中封装的请求通用类BaseRepository

代码语言:javascript复制
/// 网络请求
class BaseRepository {
  Future<Map> get(String url, {Map<String, dynamic> queryParams}) async {
    final nativeD = await Bridge.getNetComParams();
    var dio = new Dio();
    final nativeParams = ValueUtil.toMap(nativeD);
    dio.options.baseUrl = nativeParams['baseUrl'];
    dio.options.headers['sbtype'] = nativeParams['sbtype'];
    dio.options.headers['sbID'] = nativeParams['sbID'];
    dio.options.headers['version'] = nativeParams['version'];
    dio.options.headers['token'] = nativeParams['token'];
    dio.options.responseType = ResponseType.json;
    if (!queryParams.containsKey('domain_id')) {
      queryParams['domain_id'] = nativeParams['domain_id'];
    }
    log('get',
        url: nativeParams['baseUrl']   url,
        queryParams: queryParams,
        header: nativeParams);
    try {
      Response response = await dio.get(url, queryParameters: queryParams);
      debugPrint('请求数据返回:n$response');
      return response.data;
    } catch (error) {
      rethrow;
    }
  }

  Future<Map> post(String url, {Map params}) async {
    final nativeParams = await Bridge.getNetComParams();
    var dio = new Dio();
    dio.options.baseUrl = nativeParams['baseUrl'];
    dio.options.headers['sbtype'] = nativeParams['sbtype'];
    dio.options.headers['sbID'] = nativeParams['sbID'];
    dio.options.headers['version'] = nativeParams['version'];
    dio.options.headers['token'] = nativeParams['token'];
    dio.options.responseType = ResponseType.json;
    log('post',
        url: nativeParams['baseUrl']   url,
        queryParams: params,
        header: nativeParams);
    if (!params.containsKey('domain_id')) {
      params['domain_id'] = nativeParams['domain_id'];
    }
    try {
      Response response = await dio.post(url, data: params);
      debugPrint('请求数据返回:n$response');
      return response.data;
    } catch (error) {
      rethrow;
    }
  }

  void log(String method,
      {String url, Map<String, dynamic> queryParams, Map header}) {
    debugPrint(
        'nurl: $url  method: $methodnheader: $header nparams: $queryParamsn');
  }
}

dio相关设置

代码语言:javascript复制
//1. 创建dio对象:
    var dio = new Dio();
//2. 设置baseUrl:
    dio.options.baseUrl = 'baseUrl';
//3. 设置请求头:
    dio.options.headers['sbtype'] = nativeParams['sbtype'];
    dio.options.headers['sbID'] = nativeParams['sbID'];
    dio.options.headers['version'] = nativeParams['version'];
    dio.options.headers['token'] = nativeParams['token'];
//4. 请求方式:
    dio.options.responseType = ResponseType.json;
//5. 设置contentType:
    dio.options.contentType =
        ContentType.parse("application/x-www-form-urlencoded");
//6. 设置超时时长:
    dio.options.connectTimeout = 500
//7. 发送请求:
    Response response = await dio.post(url, data: params);
    debugPrint('请求数据返回:n$response');
    return response.data;

0 人点赞