日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

「Android」Bolts-更簡單的完成線程調度和任務管理

瀏覽:12日期:2022-09-27 10:14:23

使用 Bolts 可以將一個完整的操作拆分成多個子任務,這些子任務可以自由的拆分、組合和替換,每個任務作為整個任務鏈的一環可以運行在指定線程中,同時既能從上行任務中獲取任務結果,又可以向下行任務發布當前任務的結果,而不必考慮線程之間的交互。

Bolts-Android Bolts 在 Android 下的實現 Bolts-ObjC Bolts 在 OC 下的實現 Bolts-Swift Bolts 在 Swift 下的實現

前言

一個關于線程調度的簡單需求,在子線程從網絡下載圖片,并返回下載的圖片,在主線程使用該圖片更新到 UI,同時返回當前 UI 的狀態 json,在子線程將 json 數據保存到本地文件,完成后在主線程彈出提示,這中間涉及到了 4 次線程切換,同時后面的任務需要前面任務完成后的返回值作為參數。

使用 Thread + Handler 實現,線程調度很不靈活,代碼可讀性差,不美觀,擴展性差,錯誤處理異常麻煩。

String url = 'http://www.baidu.com';Handler handler = new Handler(Looper.getMainLooper());new Thread(() -> { // 下載 Bitmap bitmap = downloadBitmap(url); handler.post(() -> {// 更新 UIString json = updateUI(bitmap);new Thread(() -> { // 向存儲寫入UI狀態 saveUIState(json); // 保存成功后,提示 handler.post(() -> toastMsg('save finish.'));}).start(); });}).start();

使用 RxJava 實現,線程調度非常靈活,鏈式調用,代碼清晰,擴展性好,有統一的異常處理機制,不過 Rx 是一個很強大的庫,如果只用來做線程調度的話, Rx 就顯得有點太重了。

Observable.just(URL)// 下載.map(this::downloadBitmap).subscribeOn(Schedulers.newThread())// 更新UI.observeOn(AndroidSchedulers.mainThread()).map(this::updateUI)// 存儲 UI 狀態.observeOn(Schedulers.io()).map(this::saveUIState)// 顯示提示.observeOn(AndroidSchedulers.mainThread()).subscribe(rst -> toastMsg('save to ' + rst),// handle errorThrowable::printStackTrace);

使用 bolts 實現,線程調度靈活,鏈式調用,代碼清晰,具有良好的擴展性,具有統一的異常處理機制,雖然沒有 Rx 那么豐富的操作符,但是勝在類庫非常非常小,只有 38 KB。

Task.forResult(URL)// 下載.onSuccess(task -> downloadBitmap(task.getResult()), Task.BACKGROUND_EXECUTOR)// 更新UI.onSuccess(task -> updateUI(task.getResult()), Task.UI_THREAD_EXECUTOR)// 存儲UI狀態.onSuccess(task -> saveUIState(task.getResult()), Task.BACKGROUND_EXECUTOR)// 提示.onSuccess(task -> toastMsg('save to ' + task.getResult()), Task.UI_THREAD_EXECUT// handle error.continueWith(task -> { if (task.isFaulted()) {task.getError().printStackTrace();return false; } return true;}); 線程調度器

共有 4 種類型執行線程,將任務分發到指定線程執行,分別是

backgroud - 后臺線程池,可以并發執行任務。

scheduled - 單線程池,只有一個線程,主要用來執行 delay 操作。

immediate - 即時線程,如果線程調用棧小于 15,則在當前線程執行,否則代理給 background 。

uiThread - 針對 Android 設計,使用 Handler 發送到主線程執行。

backgroud

主要用來在后臺并發執行多任務

public static final ExecutorService BACKGROUND_EXECUTOR = BoltsExecutors.background();

在 Android 平臺下根據 CPU 核數創建線程池,其他情況下,創建緩存線程池。

background = !isAndroidRuntime() ? java.util.concurrent.Executors.newCachedThreadPool() : AndroidExecutors.newCachedThreadPool(); scheduled

主要用于任務之間做 delay 操作,并不實際執行任務。

scheduled = Executors.newSingleThreadScheduledExecutor(); immediate

主要用來簡化那些不指定運行線程的方法,默認在當前線程去執行任務,使用 ThreadLocal 保存每個線程調用棧的深度,如果深度不超過 15,則在當前線程執行,否則代理給 backgroud 執行。

private static final Executor IMMEDIATE_EXECUTOR = BoltsExecutors.immediate();// 關鍵方法@Overridepublic void execute(Runnable command) { int depth = incrementDepth(); try { if (depth <= MAX_DEPTH) { command.run(); } else { BoltsExecutors.background().execute(command) } } finally { decrementDepth(); }} uiThread

為 Android 專門設計,在主線程執行任務。

public static final Executor UI_THREAD_EXECUTOR = AndroidExecutors.uiThread();

private static class UIThreadExecutor implements Executor { @Override public void execute(Runnable command) { new Handler(Looper.getMainLooper()).post(command); }} 核心類

Task ,最核心的類,每個子任務都是一個 Task ,它們負責自己需要執行的任務。每個 Task 具有 3 種狀態 Result 、 Error 和 Cancel ,分別代表成功、異常和取消。

Continuation ,是一個接口,它就像鏈接子任務每一環的鎖扣,把一個個獨立的任務鏈接在一起。

通過 Task - Continuation - Task - Continuation ... 的形式組成完整的任務鏈,順序在各自線程執行。

創建 Task

根據 Task 的 3 種狀態,創建簡單的 Task ,會復用已有的任務對象

public static <TResult> Task<TResult> forResult(TResult value)public static <TResult> Task<TResult> forError(Exception error)public static <TResult> Task<TResult> cancelled()

使用 delay 方法,延時執行并創建 Task

public static Task<Void> delay(long delay)public static Task<Void> delay(long delay, CancellationToken cancellationToken)

使用 whenAny 方法,執行多個任務,當任意任務返回結果時,保存這個結果

public static <TResult> Task<Task<TResult>> whenAnyResult(Collection<? extends Task<TResult>> tasks)public static Task<Task<?>> whenAny(Collection<? extends Task<?>> tasks)

使用 whenAll 方法,執行多個任務,當全部任務執行完后,返回結果

public static Task<Void> whenAll(Collection<? extends Task<?>> tasks) public static <TResult> Task<List<TResult>> whenAllResult(final Collection<? extends Task<TResult>> tasks)

使用 call 方法,執行一個任務,同時創建 Task

public static <TResult> Task<TResult> call(final Callable<TResult> callable, Executor executor, final CancellationToken ct) 鏈接子任務

使用 continueWith 方法,鏈接一個子任務,如果前行任務已經執行完成,則立即執行當前任務,否則加入隊列中,等待。

public <TContinuationResult> Task<TContinuationResult> continueWith( final Continuation<TResult, TContinuationResult> continuation, final Executor executor, final CancellationToken ct)

使用 continueWithTask 方法,在當前任務之后鏈接另一個任務鏈,這種做法是為了滿足那種將部分任務組合在一起分離出去,作為公共任務的場景,他接受將另外一個完全獨立的任務鏈,追加在當前執行的任務后面。

public <TContinuationResult> Task<TContinuationResult> continueWithTask( final Continuation<TResult, Task<TContinuationResult>> continuation, final Executor executor, final CancellationToken ct)

使用 continueWhile 方法鏈接子任務,與 continueWith 區別在于,他有一個 predicate 表達式,只有當表達式成立時,才會追加子任務,這樣做是在執行任務前可以做一個攔截操作,也是為了不破環鏈式調用的整體風格。

public Task<Void> continueWhile(final Callable<Boolean> predicate, final Continuation<Void, Task<Void>> continuation, final Executor executor, final CancellationToken ct)

使用 onSuccess 和 onSuccessTask 鏈接單個任務個任務鏈,區別于 continueWith 在于, onSuccess 方法,前行任務如果失敗了,后行的任務也會直接失敗,不會再執行,但是 continueWith 的各個子任務之間沒有關聯,就算前行任務失敗,后行任務也會執行。

public <TContinuationResult> Task<TContinuationResult> onSuccess( final Continuation<TResult, TContinuationResult> continuation, Executor executor, final CancellationToken ct) 取消任務

Task 沒有 cancel 方法,而是使用了 CancellationToken 作為標記,任務執行之前會檢查這個標記,如果標記為退出,則會直接退出任務。

CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();CancellationToken token = cancellationTokenSource.getToken();Task.call((Callable<String>) () -> null,Task.BACKGROUND_EXECUTOR,token);// 取消任務cancellationTokenSource.cancel(); 異常的處理

關于異常的處理,整個機制下來,每個任務作為一個獨立的單位,異常會被統一捕捉,因此不必針對任務中的方法進行單獨的處理。

如果使用了 continueWith 鏈接任務,那么當前任務的的異常信息,將會保存在當前 Task 中在下行任務中進行處理,下行任務也可以不處理這個異常,直接執行任務,那么這個異常就到這里停止了,不會再向下傳遞,也就是說,只有下行任務才知道當前任務的結果,不管是成功還是異常。

當然了,如果任務之間有關聯,由于上行任務的異常極大可能造成當前任務的異常,那么當前任務異常的信息,又會向下傳遞,但是上行任務的異常就到這里為止了。

如果使用 onSuccess 之類的方法,如果上行任務異常了,那么下行任務根本不會執行,而是直接將異常往下面傳遞,直到被處理掉。

任務的分離和組合

我們可以將一個完整的操作細分成多個任務,每個任務都遵循單一職責的原則而盡量簡單,這樣可以在任務之間再穿插新的任務,或者將部分任務分離出來組合到一起等。

擴展性

我們可以在兩個細分的任務之間添加一個新的操作,而不影響上行和下行任務,如我們給文章開頭的需求中更新 UI 之前,將 Bitmap 先保存到本地。

Task.forResult(URL)// 下載.onSuccess(task -> downloadBitmap(task.getResult()), Task.BACKGROUND_EXECUTOR)// 保存在本地.onSuccess(task -> saveBitmapToFile(task.getResult()),Task.BACKGROUND_EXECUTOR)// 更新UI.onSuccess(task -> updateUI(task.getResult()), Task.UI_THREAD_EXECUTOR)... 復用性

對一些公共的操作,可以單獨分離成新的任務,當需要做類似操作時,即可復用這部份功能,如可以將 下載圖片并更新 UI 保存狀態并彈出提示 兩塊功能分離出來,作為公共的任務。

// 下載圖片->更新UIpublic Continuation<String, Task<String>> downloadImageAndUpdateUI() { return task -> Task.call(() -> downloadBitmap(task.getResult()), Task.BACKGROUND_EXECUTOR) .continueWith(taskWithBitmap -> updateUI(taskWithBitmap.getResult()), Task.UI_THREAD_EXECUTOR);}// 保存狀態->提示信息public Continuation<String, Task<Boolean>> saveStateAndToast() { return task -> Task.call(() -> saveUIState(task.getResult()), Task.BACKGROUND_EXECUTOR) .continueWith(taskWithPath -> toastMsg('save to ' + taskWithPath.getResult()));}

使用分離的任務

Task.forResult(URL).continueWithTask(downloadImageAndUpdateUI()).continueWithTask(saveStateAndToast())... 總結

在 Task 中有一個 continuations 是當前任務后面追加的任務列表,當當前任務成功、異常或者取消時,會去執行列表中的后續任務。

通常情況下,我們使用鏈式調用構建任務鏈,結果就是一條沒有分支的任務鏈。

添加任務時:每次添加一個 Continuation ,就會生成一個 Task ,加到上行任務的 continuations 列表中,等待執行,同時返回當前的 Task ,以便后面的任務可以鏈接到當前任務后面。

執行任務時:當前任務執行完之后,結果可能有 3 種,都會被保存到當前的 Task 中,然后檢查 continuations 列表中的后續任務,而當前的 Task 就會作為參數,傳遞到后續鏈接的任務中,來讓后面的任務得知上行任務的結果。

來自:https://segmentfault.com/a/1190000012091542

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产综合亚洲精品一区二| 日韩一区二区久久| 99久久www免费| 久久超碰99| 久久狠狠亚洲综合| 亚洲精品黄色| 美女精品在线| 狠狠爱成人网| 日韩成人免费| 久久一区精品| 欧美一区二区三区免费看| 亚洲综合电影一区二区三区| 桃色一区二区| 97精品国产一区二区三区| 国产精品久久777777毛茸茸| 日韩精品福利一区二区三区| 丝袜国产日韩另类美女| 午夜电影亚洲| 99精品视频精品精品视频| 水蜜桃精品av一区二区| 久久精品国产网站| 久久精品国产免费| 麻豆精品在线视频| 日韩中文字幕无砖| 中文字幕一区二区三区四区久久| 在线综合亚洲| 日韩精品一卡二卡三卡四卡无卡 | 日韩制服丝袜av| 日韩一区二区免费看| 伊人久久成人| 国产美女一区| 久久亚洲一区| 亚洲乱码视频| 日韩va亚洲va欧美va久久| 日本精品国产| 91免费精品国偷自产在线在线| 日韩精品久久久久久久软件91| 红桃视频欧美| 蜜桃伊人久久| 日韩国产在线观看一区| 国产欧美午夜| 精品国产欧美日韩| 欧洲一区二区三区精品| 91成人精品视频| 中文字幕免费一区二区| 欧美三级第一页| 欧美a一区二区| 黄色在线网站噜噜噜| 1000部精品久久久久久久久| 99国产精品久久久久久久| 一区二区电影| 欧美在线日韩| 久久久91麻豆精品国产一区| 久久久久九九精品影院| 成人在线超碰| 欧洲激情综合| 色综合视频一区二区三区日韩 | 神马久久午夜| 国产精品成人3p一区二区三区| 欧美国产另类| 欧美香蕉视频| 伊人久久婷婷| 日韩一区二区三区免费视频| 国产精品久久久久久久免费软件| 国产一区二区亚洲| 精品91久久久久| 日韩av影院| 成人午夜网址| 日韩午夜在线| 国产欧美日韩视频在线 | 精品国产午夜肉伦伦影院| 99久久夜色精品国产亚洲狼| 国产精品日韩久久久| 日韩不卡一二三区| 91亚洲国产成人久久精品| 亚洲高清激情| 欧美一区自拍| 三级精品视频| 日韩精品视频中文字幕| 久久久久久色 | 日韩激情视频网站| 久久久久久色| 欧美日韩国产在线观看网站 | 欧美午夜不卡影院在线观看完整版免费| 麻豆精品网站| 国产在线观看91一区二区三区 | 国产精品久久久久久久久妇女| 最新亚洲激情| 日韩精品一区二区三区免费视频| 精品一区不卡| 亚洲丝袜美腿一区| 亚洲国产福利| 日韩精品免费观看视频| 免费观看亚洲| 黄色亚洲大片免费在线观看| 国产精品久久亚洲不卡| 2023国产精品久久久精品双| 国产精品三级| 午夜亚洲一区| 国产成人a视频高清在线观看| 日韩中文字幕1| 久久精品国产大片免费观看| 美女精品视频在线| 日韩av网站免费在线| 亚洲免费中文| 欧美.日韩.国产.一区.二区| 日韩精品看片| 日韩欧美在线中字| 免费看av不卡| 久久精品毛片| 麻豆成人综合网| 美女国产精品久久久| 国产日产精品_国产精品毛片| 亚洲精品日本| 日韩精品欧美精品| 深夜日韩欧美| 免费观看久久久4p| 亚洲综合婷婷| 日韩精品第一| 久久精品72免费观看| 国产精品一区二区av日韩在线| 欧美日韩a区| 国产精品入口久久| 久久男人av| 成人国产精品久久| 日韩成人高清| 久久久久网站| 亚洲精品网址| 中文精品电影| 国产亚洲久久| 精品网站aaa| 日韩大片在线| 欧美精选一区二区三区| 国产视频一区欧美| 亚洲精品激情| 国产丝袜一区| 成人午夜网址| 亚洲www啪成人一区二区| 999国产精品999久久久久久| 久久91导航| 久久xxxx| 日本91福利区| 美腿丝袜在线亚洲一区| 日韩美女一区二区三区在线观看| 欧美日韩在线观看视频小说| 在线综合亚洲| 日韩av中文字幕一区| 九九九精品视频| 久久精品影视| 老鸭窝亚洲一区二区三区| 日韩高清电影一区| 久久中文字幕一区二区三区| 国产伦久视频在线观看| 一区二区三区四区在线看| 免费国产自线拍一欧美视频| 日韩中文字幕在线一区| 久久一区视频| 极品裸体白嫩激情啪啪国产精品| 蜜桃视频在线观看一区| 国产精品久久免费视频| 精品免费av在线| 亚洲欧洲专区| 久久久精品国产**网站| 99精品美女| 日本不卡高清| 97精品视频在线看| 丝袜美腿亚洲一区| 捆绑调教美女网站视频一区| 国产99精品一区| 在线精品一区二区| 麻豆久久一区二区| 尤物网精品视频| 国产精品高清一区二区| 日韩精品网站| 日韩av一级片| 亚洲精品**中文毛片| 美女日韩在线中文字幕| 国产精区一区二区| 国产一区久久| 免费一级片91| 麻豆91精品视频| 亚洲一区黄色| 麻豆一区二区99久久久久| 亚洲作爱视频| 国产极品嫩模在线观看91精品| 欧美精品一区二区三区精品| 国产精品综合色区在线观看| 国产一区清纯| 久久中文字幕一区二区三区| 国产视频一区欧美| 精品高清久久| 亚洲乱码一区| 欧美少妇精品| 日韩二区三区四区| 欧美日韩精品一本二本三本| 精品资源在线| 日韩福利视频网| 99热精品在线观看| 超碰超碰人人人人精品| 91麻豆精品|