Flutter - App開發(fā)中的常見同步/異步場景

代碼


import 'package:dio/dio.dart';

//使用async和await做異步調(diào)用.
void getHttp() async {
  try {
    Response response = await Dio().get("https://www.baidu.com");
    print(response);
    print("------------");
    print(response.data.toString());
  } catch(e){
    print(e);
  }
}

void main()  {
  // getHttp();

  //單個異步事件
  Future.delayed(new Duration(seconds:2),(){
    return 'hi world!';
  }).then((data){
    print(data);
  } );

  //多個異步事件
  Future.wait([
    Future.delayed(new Duration(seconds: 2),(){
      return "hello";
    }),
    Future.delayed(new Duration(seconds: 4),(){
      return "world!";
    })
  ]).then((results){
    print(results[0]+results[1]);
  }).catchError((e){
    print(e);
  });

}




場景1

界面初始化時,某個變量A,訪問數(shù)據(jù)庫或網(wǎng)絡(luò),拿到數(shù)據(jù), 返回給界面.
如果異步操作, 界面可能會在A拿到數(shù)據(jù)之前就初始化完成,這時界面收到的就是null.
這個場景只能用同步,保證A拿到數(shù)據(jù)之后,界面才初始化.(或者異步,A拿到值后,使界面重新刷新,這會影響用戶體驗(yàn))

asyncawait : 將異步方法按同步方法操作

  • async 描述一個執(zhí)行異步操作的方法
  • await表示一直等待異步方法返回結(jié)果,才繼續(xù)往后執(zhí)行
 Future<String> method5() async {
    return "5";
  }
  void testD() async {
    print(1);
    String f5 = await method5();
    print(f5);
    print(3);
  }
結(jié)果:
1
5
3

場景2

用戶做完一個題目,點(diǎn)擊下一題,需要將用戶做題結(jié)果存到數(shù)據(jù)庫,但是這可以異步操作, 使用戶點(diǎn)擊下一題時馬上顯示下一題的界面,不需要用戶等待上一題結(jié)果存數(shù)據(jù)庫的時間.

當(dāng)遇到有需要延遲的運(yùn)算(async)時,將其放入到延遲運(yùn)算的隊(duì)列(await)中去,把不需要延遲運(yùn)算的部分先執(zhí)行掉,最后再來處理延遲運(yùn)算的部分。

代碼示例:

import 'package:dio/dio.dart';


/* 這個示例是, 在main函數(shù)里, 用getData請求網(wǎng)絡(luò)API, 同時異步打印一句話.
   可以看到在getData請求網(wǎng)絡(luò)api完成之前, 這句話已經(jīng)打印完成了 */

void main() {

  getData().then((result) {
    print("接口返回的數(shù)據(jù)是:${result}");
  }).whenComplete((){
    print("異步任務(wù)處理完成");
  }).catchError((){
    print("出現(xiàn)異常了");
  });

  print("我是在請求數(shù)據(jù)后面的代碼呦!"); //異步打印出來

}

/**
 * 請求接口獲取數(shù)據(jù)
 */
Future<Response> getData() async {
  String url = "http://v.juhe.cn/toutiao/index";
  String key = "4c52313fc9247e5b4176aed5ddd56ad7";
  String type = "keji";

  print("開始請求數(shù)據(jù)↓↓↓↓↓↓↓↓↓↓↓↓");
  Response response =
      await Dio().get(url, queryParameters: {"type": type, "key": key});

  print("請求完成↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");

  return response;
}

結(jié)果:

開始請求數(shù)據(jù)↓↓↓↓↓↓↓↓↓↓↓↓
我是在請求數(shù)據(jù)后面的代碼呦!
請求完成↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
接口返回的數(shù)據(jù)是:{"reason":"成功的返回","result":{"stat":"1","data":[{"uniquekey":"348c7f269f45c447bee1cb7be4098529","title":"Vivid Audio Giya G1S,魔人布?xì)W和他的新裝","date":"2020-03-18 14:20","category":"科技","author_name":"家電論壇","url":"https://v.juhe.cn/toutiao/s?id=https%3A%2F%2Fmini.eastday.com%2Fmobile%2F200318142004727.html","thumbnail_pic_s":"https://08imgmini.eastday.com/mobile/20200318/20200318142004_c09487f56a73d96ba7c2bcc60193ed2e_7_mwpm_03200403.jpg","thumbnail_pic_s02":"http://08imgmini.eastday.com/mobile/20200318/20200318142004_c09487f56a73d96ba7c2bcc60193ed2e_6_mwpm_03200403.jpg","thumbnail_pic_s03":"http://08imgmini.eastday.com/mobile/20200318/20200318142004_c09487f56a73d96ba7c2bcc60193ed2e_3_mwpm_03200403.jpg"}]},"error_code":0}
異步任務(wù)處理完成

場景3

在數(shù)據(jù)庫里根據(jù) id 查詢名字:

Future queryName(int id) {
  // 創(chuàng)建一個completer
  var completer = new Completer();
  
  // 查詢數(shù)據(jù)庫,然后根據(jù)成功或者失敗執(zhí)行相應(yīng)的callback回調(diào),這個過程是異步的
  database.query("select name from user where id = $id", (results) {
    completer.complete(results);
  }, (error) {
    completer.completeError(error);
  });
  
  // return 在query結(jié)果出來之前就會被執(zhí)行
  return completer.future;
}

如何使用 queryName 呢?常見兩種方式來"打開箱子":await 或者 then。

await:

void runFuturesDemo2() async {
    try {
        final name = await queryName(100);  
        print("id 100 user name is $name");
    } catch (e) {
        print(e.toString());
    } finally {
        print("finally finished.");
    }
}

then:

void runFuturesDemo2() {
  queryName(100).then((name) {
    print("id 100 user name is $name");
  }, onError: (e) {
    print(e.toString());
  }).whenComplete(() {
    print("finally finished.");
  });
}

參考1
參考2
參考3
參考4

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、async/await的優(yōu)點(diǎn) 1)方便級聯(lián)調(diào)用:即調(diào)用依次發(fā)生的場景; 2)同步代碼編寫方式: Promise...
    puxiaotaoc閱讀 105,895評論 7 62
  • JavaScript執(zhí)行機(jī)制,重點(diǎn)有兩點(diǎn): 1.JavaScript是一門單線程語言。2.Event Loop(事...
    小泡_08f5閱讀 11,870評論 2 22
  • __block和__weak修飾符的區(qū)別其實(shí)是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,585評論 0 6
  • JS為什么是單線程的? 最初設(shè)計(jì)JS是用來在瀏覽器驗(yàn)證表單操控DOM元素的是一門腳本語言,如果js是多線程的那么兩...
    船長___閱讀 2,317評論 1 15
  • 簡書是一個平臺,更是一個社群。我去年很遲才接觸簡書。以日記的形式堅(jiān)持日更,在簡書走走逛逛中遇見各種各樣的有趣又可愛...
    方媛詩閱讀 474評論 1 9

友情鏈接更多精彩內(nèi)容