亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Flutter 假異步的實(shí)現(xiàn)示例

 更新時(shí)間:2019年11月01日 14:47:08   作者:前行的烏龜  
這篇文章主要介紹了Flutter 假異步的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

就像 android 有 handle 一樣,消息隊(duì)列這東西好像還真是系統(tǒng)必備,F(xiàn)lutter 也有自己的消息隊(duì)列,只不過隊(duì)列直接封裝在了 Dart 的線程類型 Isolate 里面了,不過 Flutter 還是提供了 Futrue 這個(gè) API 來專門來操作各種消息,以及實(shí)現(xiàn)基于消息隊(duì)列的假異步

Flutter 的“異步”機(jī)制

這里的異步是加了引號(hào)的,可見此異步非真異步,而是假異步。Flutter 的 異步 不是開新線程,而是往所屬線程的 消息隊(duì)列 中添加任務(wù),當(dāng)然大家也可以按上文那樣自己展開真異步操作

Flutter 對(duì)代碼分2類: 同步代碼和異步代碼

  • 同步代碼:傳統(tǒng)一行行寫下來,一行行執(zhí)行的代碼
  • 異步代碼:通過 Future API 把任務(wù)添加到 Isolate 所屬消息隊(duì)列執(zhí)行的偽異步
  • 執(zhí)行順序:先運(yùn)行同步代碼,再運(yùn)行異步代碼

為啥,很明顯啊,異步代碼是往消息隊(duì)列里添加任務(wù),那肯定得等現(xiàn)在的代碼運(yùn)行完了,線程有空閑了才能開始執(zhí)行消息隊(duì)列里的任務(wù)呀~

舉個(gè)例子:

void test() {
  print("AA");
  Future(() => print("Futrue"));
  print("BB");
}
~~~~~~~~~~~log~~~~~~~~~~~~~
I/flutter (10064): AA
I/flutter (10064): BB
I/flutter (10064): Futrue

print("Futrue")) 任務(wù)等到最后才執(zhí)行的...

Flutter 提供了往 消息隊(duì)列 添加數(shù)據(jù)的 API: Future

往 MicroTask 隊(duì)列添加任務(wù)

scheduleMicrotask((){
 // ...code goes here...
}); 

new Future.microtask((){
  // ...code goes here...
});

往 Event 隊(duì)列添加任務(wù)

new Future(() {
 // ...code goes here...
});

Future 的基本使用

Future 對(duì)象是 Flutter 專門提供的,基于消息隊(duì)列實(shí)現(xiàn)異步的類,F(xiàn)uture 對(duì)象會(huì)把自身當(dāng)做一個(gè)任務(wù)添加到消息隊(duì)列中去排隊(duì)執(zhí)行

Future 對(duì)象接受的是一個(gè)函數(shù),就是要執(zhí)行的任務(wù),用 () => ... 簡(jiǎn)寫也是可以的

void task() {
  print("AA");
}

var futrue = Future(task);

創(chuàng)建 Future 任務(wù)方式:

  • Future()
  • Future.microtask()
  • Future.sync() - 同步任務(wù)
  • Future.value()
  • Future.delayed() - 延遲xx時(shí)間添加任務(wù)
  • Future.error() - 錯(cuò)誤處理

我們來看幾個(gè)代表性的:

Future.sync() - 阻塞任務(wù),會(huì)阻塞當(dāng)前代碼,sync 的任務(wù)執(zhí)行完了,代碼才能走到下一行

void test() {
  print("AA");
  Future.sync(() => print("Futrue"));
  print("BB");
}
~~~~~~~~~~~~log~~~~~~~~~~~~~~
I/flutter (10573): AA
I/flutter (10573): Futrue
I/flutter (10573): BB

Future.delayed() - 延遲任務(wù),指定xx時(shí)間后把任務(wù)添加到消息隊(duì)列,要是消息隊(duì)列前面有人執(zhí)行的時(shí)間太長(zhǎng)了,那么執(zhí)行時(shí)間點(diǎn)就不能把握了,這點(diǎn)大家要知道

void test() {
  print("AA");
  Future.delayed(Duration(milliseconds: 500),() => print("Futrue"));
  print("BB");
}
~~~~~~~~~~~~log~~~~~~~~~~~~~~
I/flutter (10573): AA
I/flutter (10573): BB
I/flutter (10573): Futrue

Future 的鏈?zhǔn)秸{(diào)用

Future 也支持鏈?zhǔn)秸{(diào)用的,在 API 使用上也是很靈活的,提供了下面的選擇給大家

.then - 在 Future 執(zhí)行完后執(zhí)行,相當(dāng)于一個(gè) callback,而不是重新創(chuàng)建了一個(gè) Future

 Future.delayed(Duration(seconds: 1),(){
   print(("AAA"));
   return "AA";
  }).then((value){
   print(value);
  });

.catchError - future 不管在任何位置發(fā)生了錯(cuò)誤,都會(huì)立即執(zhí)行 catchError

  Future.delayed(Duration(seconds: 1),(){
   throw Exception("AAA");
  }).then((value){
   print(value);
  }).catchError((error){
   print(error);
  });

.whenComplete - 不管是否發(fā)生異常,在執(zhí)行完成后,都會(huì)執(zhí)行該方法

 Future.delayed(Duration(seconds: 1), () {
   throw Exception("AAA");
  }).then((value) {
   print(value);
  }).catchError((error) {
   print(error);
  }).whenComplete(() {
   print("complete...");
  });

.wait - 可以等待所有的 future 都執(zhí)行完畢再走 then 的方法

Future.wait([
   // 2秒后返回結(jié)果
   Future.delayed(new Duration(seconds: 2), () {
    return "hello";
   }),
   // 4秒后返回結(jié)果
   Future.delayed(new Duration(seconds: 4), () {
    return " world";
   })
  ]).then((results) {
   print(results[0] + results[1]);
  }).catchError((e) {
   print(e);
  });

大家想想啊

Futrue()
  .then()
  .then()
  ...

這樣的鏈?zhǔn)綄懛ú痪褪菢?biāo)準(zhǔn)的去 callback 回調(diào)地獄的方式嘛

async/await 關(guān)鍵字

async/await 這組關(guān)鍵字是系統(tǒng)提供的另一種實(shí)現(xiàn) 異步 任務(wù)的 API, async/await 底層還是用 Futrue 實(shí)現(xiàn)的,從使用上看是對(duì) Futrue 的簡(jiǎn)化,本質(zhì)上還是基于 消息隊(duì)列 實(shí)現(xiàn)的異步,是 假異步 ,和 Isoalte 是不一樣的

async/await 的特點(diǎn)就是: 成對(duì)出現(xiàn)

  • async - 修飾方法,用 async 聲明的方法都是耗時(shí)的
  • await - 調(diào)用 async 方法時(shí)使用,也可以在 async 方法內(nèi)部是適用,await 表示阻塞,下面的任務(wù)必須等 await 調(diào)用的方法執(zhí)行完之后才能執(zhí)行

比如這樣:

 anysncTest() async {
  print("async 休眠 start...");
  sleep(Duration(seconds: 1));
  print("async 休眠 end...");
 }

await anysncTest();

本質(zhì)上 await 調(diào)用的方法其實(shí)是把這個(gè)方法包裝到 Futrue 中去消息隊(duì)列里執(zhí)行,只不過是: Future.sync() 阻塞式的 Future 任務(wù)

async 在布局中也是可以直接用的

class TestWidgetState extends State<TestWidget> {
 int _count = 0;
 
 @override
 Widget build(BuildContext context) {
  return Material(
    FlatButton(
      onPressed: () async {
        _count = countEven(1000000000);
        setState(() {});
      },
      child: Text(
        _count.toString(),
      )),
  );
 }

async/await 是阻塞式的函數(shù)

實(shí)驗(yàn)1:

 // 這是異步任務(wù)代碼
 aaa() async{
  print("main1...");
  await anysncTest();
  print("main2...");
  print("main3...");
 }

 anysncTest() async {
  print("async 休眠 start...");
  sleep(Duration(seconds: 1));
  print("async 休眠 end...");
 }
 
 // 點(diǎn)擊按鈕去執(zhí)行
  Widget build(BuildContext context) {
  return RaisedButton(
   child: (Text("click!")),
   onPressed: () async {
    await aaa();
   },
  );
 }

 

可以看到 async/await

執(zhí)行的方法的確是阻塞時(shí)的,至少在這個(gè) async 方法里絕對(duì)是阻塞式的

實(shí)驗(yàn)2:

那么范圍擴(kuò)展一下,在 async 外面再來看看 async/await 是不是阻塞式的? 有人說 async/await 和協(xié)程一樣 ,協(xié)程的關(guān)鍵點(diǎn)在于非競(jìng)爭(zhēng)式資源,協(xié)程的概念中,當(dāng)多個(gè)協(xié)程中有一個(gè)協(xié)程掛起之后,并不會(huì)阻塞 CPU,CPU 回去執(zhí)行其他協(xié)程方法,直到有空閑了再來執(zhí)行之前掛起后恢復(fù)的協(xié)程,雖然在協(xié)程看來我掛起了線程,但其實(shí) CPU 不會(huì)被協(xié)程掛起阻塞,這點(diǎn)就是協(xié)程的核心優(yōu)勢(shì),大大提升多線程下的執(zhí)行效率。

從這點(diǎn)出發(fā)我們就能知道 async/await 是不是又一個(gè)協(xié)程了,看看他阻塞 CPU,我們?cè)?await 之后看看 async 后面的代碼會(huì)不會(huì)執(zhí)行就 OK了

 // 還是這組方法
 aaa() async{
  print("main1...");
  await anysncTest();
  print("main2...");
  print("main3...");
 }

 anysncTest() async {
  print("async 休眠 start...");
  sleep(Duration(seconds: 1));
  print("async 休眠 end...");
 }
 
 // 執(zhí)行,注意此時(shí)按鈕的點(diǎn)擊方法不是 async 的
 Widget build(BuildContext context) {
  return RaisedButton(
   child: (Text("click!")),
   onPressed: () {
    print("click1...");
    aaa();
    print("click2...");
    print("click3...");
   },
  );
 }
I/flutter ( 5733): click1...
I/flutter ( 5733): main1...
I/flutter ( 5733): async 休眠 start...
I/flutter ( 5733): async 休眠 end...
I/flutter ( 5733): click2...
I/flutter ( 5733): click3...
I/flutter ( 5733): main2...
I/flutter ( 5733): main3...

await 阻塞是真的阻塞 CPU 了,所以 async/await 不是協(xié)程,但是大家注意啊,在 await 結(jié)速阻塞之后執(zhí)行的是 click2 也就是 async 外部的方法,說明 await 標(biāo)記的方法返回的都是 Futrue 對(duì)象的說法是正確的,隊(duì)列只有在線程空閑時(shí)才會(huì)執(zhí)行,顯然此時(shí)線程不是空閑的,點(diǎn)擊方法還沒執(zhí)行完呢

實(shí)驗(yàn)3:

這次做對(duì)比實(shí)驗(yàn),把點(diǎn)擊事件也變成 async 的看看執(zhí)行順序

 // 還是這組方法
 aaa() async{
  print("main1...");
  await anysncTest();
  print("main2...");
  print("main3...");
 }

 anysncTest() async {
  print("async 休眠 start...");
  sleep(Duration(seconds: 1));
  print("async 休眠 end...");
 }
 
 // 執(zhí)行
  Widget build(BuildContext context) {
  return RaisedButton(
   child: (Text("click!")),
   onPressed: () async {
    print("click1...");
    await aaa();
    print("click2...");
    print("click3...");
   },
  );
 }
I/flutter ( 5733): click1...
I/flutter ( 5733): main1...
I/flutter ( 5733): async 休眠 start...
I/flutter ( 5733): async 休眠 end...
I/flutter ( 5733): main2...
I/flutter ( 5733): main3...
I/flutter ( 5733): click2...
I/flutter ( 5733): click3...

這樣看的話在 async 方法內(nèi)部,是嚴(yán)格按照順序執(zhí)行的

async 方法的格式

1. async 標(biāo)記的方法返回值都是 Futrue 類型的

上文書哦說 await 調(diào)用的方法返回的都是 Futrue 對(duì)象,那么就是說在聲明 async 函數(shù)時(shí),返回值都是 Futrue 類型的,F(xiàn)utrue 內(nèi)部包裹實(shí)際的返回值類型

Futrue<String> getData() async {
 data = await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});  
}

Futrue<String> 我們可以不寫,dart 也會(huì)自動(dòng)推斷出來,但是我們一定要知道是 Futrue 類型的,要不有時(shí)會(huì)報(bào)類型錯(cuò)誤

我們?cè)谟玫臅r(shí)候都是配合 await 使用的,這時(shí)候可以直接用具體類型值接返回值了

String data = await getData();

記?。?/p>

Future就是event,很多Flutter內(nèi)置的組件比如前幾篇用到的Http(http請(qǐng)求控件)的get函數(shù)、RefreshIndicator(下拉手勢(shì)刷新控件)的onRefresh函數(shù)都是event。每一個(gè)被await標(biāo)記的句柄也是一個(gè)event,每創(chuàng)建一個(gè)Future就會(huì)把這個(gè)Future扔進(jìn)event queue中排隊(duì)等候安檢~

Stream

StreamFuture 一樣都是假異步操作,區(qū)別是 Stream 可以接受多次數(shù)據(jù),我不詳細(xì)展開了,有待以后詳細(xì)研究

Stream.fromFutures([
 // 1秒后返回結(jié)果
 Future.delayed(new Duration(seconds: 1), () {
  return "hello 1";
 }),
 // 拋出一個(gè)異常
 Future.delayed(new Duration(seconds: 2),(){
  throw AssertionError("Error");
 }),
 // 3秒后返回結(jié)果
 Future.delayed(new Duration(seconds: 3), () {
  return "hello 3";
 })
]).listen((data){
  print(data);
}, onError: (e){
  print(e.message);
},onDone: (){

});

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android簡(jiǎn)單實(shí)現(xiàn)計(jì)算器功能

    Android簡(jiǎn)單實(shí)現(xiàn)計(jì)算器功能

    這篇文章主要為大家詳細(xì)介紹了Android簡(jiǎn)單實(shí)現(xiàn)計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Android文件存儲(chǔ)SharedPreferences源碼解析

    Android文件存儲(chǔ)SharedPreferences源碼解析

    SharedPreferences是安卓平臺(tái)上一個(gè)輕量級(jí)的存儲(chǔ)類,用來保存應(yīng)用的一些常用配置,比如Activity狀態(tài),Activity暫停時(shí),將此activity的狀態(tài)保存到SharedPereferences中;當(dāng)Activity重載,系統(tǒng)回調(diào)方法onSaveInstanceState時(shí),再?gòu)腟haredPreferences中將值取出
    2022-08-08
  • RecyclerView使用詳解

    RecyclerView使用詳解

    本文主要對(duì)RecyclerView的使用進(jìn)行了詳細(xì)介紹,文章結(jié)尾附上源碼下載,具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • Android自定義商品購(gòu)買數(shù)量加減控件

    Android自定義商品購(gòu)買數(shù)量加減控件

    這篇文章主要為大家詳細(xì)介紹了Android自定義商品購(gòu)買數(shù)量加減控件的相關(guān)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • android實(shí)現(xiàn)文件下載功能

    android實(shí)現(xiàn)文件下載功能

    這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)文件下載功能,android在網(wǎng)絡(luò)上下載文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Android項(xiàng)目實(shí)戰(zhàn)之仿網(wǎng)易頂部導(dǎo)航欄效果

    Android項(xiàng)目實(shí)戰(zhàn)之仿網(wǎng)易頂部導(dǎo)航欄效果

    這篇文章主要為大家詳細(xì)介紹了Android項(xiàng)目實(shí)戰(zhàn)之仿網(wǎng)易頂部導(dǎo)航欄效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Android:“萬(wàn)能”Activity重構(gòu)篇

    Android:“萬(wàn)能”Activity重構(gòu)篇

    本文主要介紹了mvp以及每一層,以及使用mvp來重構(gòu)“萬(wàn)能”Activity,其實(shí)每一層需要注意的東西還有很多,比如model層是最難寫的一層。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • Android中隱藏狀態(tài)欄和標(biāo)題欄的方法匯總(隱藏狀態(tài)欄、標(biāo)題欄的五種方法)

    Android中隱藏狀態(tài)欄和標(biāo)題欄的方法匯總(隱藏狀態(tài)欄、標(biāo)題欄的五種方法)

    這篇文章主要介紹了Android中隱藏狀態(tài)欄和標(biāo)題欄的方法匯總(隱藏狀態(tài)欄、標(biāo)題欄的五種方法),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-02-02
  • Android中巧妙的實(shí)現(xiàn)緩存詳解

    Android中巧妙的實(shí)現(xiàn)緩存詳解

    采用緩存,可以進(jìn)一步大大緩解數(shù)據(jù)交互的壓力,有的時(shí)候?yàn)榱丝焖俨樵儠?huì)被多次調(diào)用的數(shù)據(jù),或者構(gòu)建比較廢時(shí)的實(shí)例,我們一般使用緩存的方法。無(wú)論大型或小型應(yīng)用,靈活的緩存可以說不僅大大減輕了服務(wù)器的壓力,而且因?yàn)楦焖俚挠脩趔w驗(yàn)而方便了用戶。下面來一起看看吧。
    2016-11-11
  • Android中BaseAdapter的用法分析與理解

    Android中BaseAdapter的用法分析與理解

    這篇文章主要介紹了Android中BaseAdapter的用法分析與理解,結(jié)合一個(gè)項(xiàng)目開發(fā)中BaseAdapter的使用分析了BaseAdapter的功能、作用及用法理解,需要的朋友可以參考下
    2016-08-08

最新評(píng)論