標籤:
Android 下的 bolts tasks
本文主要介紹的是在Android 下使用 bolts tasks, bolts tasks 可以很方便的讓我們將一些非同步task關聯起來執行。讓這些tasks有順序的執行(當我們一個task的執行要基於另一個task的時候)。
1. github 地址 Bolts-Android2. gradle中引用
dependencies {compile ‘com.parse.bolts:bolts-android:1.2.0‘}
3. 具體的使用
(我也是初學者,只是偶爾用過一次。理解的也很簡單,我只是列出這個庫裡面我用到的一些方法,望見諒)
既然是task 肯定要知道他在那個線程中啟動並執行。 Boots tasks 源碼中總共有三種形式
/** * An {@link java.util.concurrent.Executor} that executes tasks in parallel. */ public static final ExecutorService BACKGROUND_EXECUTOR = BoltsExecutors.background(); /** * An {@link java.util.concurrent.Executor} that executes tasks in the current thread unless * the stack runs too deep, at which point it will delegate to {@link Task#BACKGROUND_EXECUTOR} in * order to trim the stack. */ private static final Executor IMMEDIATE_EXECUTOR = BoltsExecutors.immediate(); /** * An {@link java.util.concurrent.Executor} that executes tasks on the UI thread. */ public static final Executor UI_THREAD_EXECUTOR = AndroidExecutors.uiThread();
BACKGROUND_EXECUTOR 我把他理解成是後台線程。
IMMEDIATE_EXECUTOR 我把他理解成是當前線程,當然如果當前線程路徑太深也會是後台線程。
UI_THREAD_EXECUTOR 我把他理解是UI線程(Handler(Looper.getMainLooper()).post())
1). 執行單個的任務
Task.callInBackground(new Callable<Boolean>() { @Override public Boolean call() throws Exception { // 處理一些具體的動作 return true; } });
我把他理解成是後台非同步處理。
Task.call(new Callable<Boolean>() { @Override public Boolean call() throws Exception { // 處理一些具體的動作 return true; } });
我把他理解成是在同一個線程執行。
Task.call(new Callable<Boolean>() { @Override public Boolean call() throws Exception { // 處理一些具體的動作 return true; } }, Task.UI_THREAD_EXECUTOR);
UI線程執行。
2). 多個任務順序執行
Task.call(new Callable<Void>() { @Override public Void call() throws Exception { // show waiting dialog showWaitingDialog(R.string.waiting_for_get_wifi_mode); return null; } }).onSuccess(new Continuation<Void, WifiMode>() { @Override public WifiMode then(Task<Void> task) throws Exception { RouterManager routerManager = getRouterManager(); return routerManager.getWifiMode(); } }, Task.BACKGROUND_EXECUTOR).continueWith(new Continuation<WifiMode, Void>() { @Override public Void then(Task<WifiMode> task) throws Exception { // dismiss dialog dismissWaitingDialog(); // set ui if (task.isFaulted()) { changeUiByWifiMode(mConnectMode); } else if (task.isCompleted()) { mConnectMode = task.getResult(); changeUiByWifiMode(mConnectMode); } return null; } }, Task.UI_THREAD_EXECUTOR);
第一個任務(Task.call的任務) 是在調用者的同一個線程執行。我這裡做的動作只是顯示waitting dialog。
第二個任務(onSuccess跟上的任務)注意onSuccess的第二個參數是 Task.BACKGROUND_EXECUTOR 表示在後台執行可以做一些耗時的操作,並且會把傳回值傳到下一個任務。
第三個任務(continueWith跟上的任務)是擷取到上一個任務的傳回值。在做一些具體的動作。
onSuccess 顧名思義是在第一個任務成功執行的基礎上在執行的(第一個任務沒有拋異常)。continueWith 顧名思義是在上一個任務執行完的基礎上執行的不管有沒有拋異常都會執行(當有異常的時候我們會在下文中提到怎麼擷取到異常)。
3). 多個任務並存執行。
Task.call(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return true; } }, Task.UI_THREAD_EXECUTOR).onSuccess(new Continuation<Boolean, List<Task<ReachableIP>>>() { @Override public List<Task<ReachableIP>> then(Task<Boolean> task) throws Exception { List<Task<ReachableIP>> tasks = new ArrayList<Task<ReachableIP>>(); tasks.add(getGatewayAsync()); tasks.add(getRouterWanIpAsync()); Task.whenAll(tasks).waitForCompletion(); return tasks; } }, Task.BACKGROUND_EXECUTOR).onSuccess(new Continuation<List<Task<ReachableIP>>, ReachableIP>() { @Override public ReachableIP then(Task<List<Task<ReachableIP>>> task) throws Exception { List<Task<ReachableIP>> tasks = task.getResult(); for (Task<ReachableIP> t : tasks) { if (t.isCompleted()) { ReachableIP reachableIP = t.getResult(); } } return null; } }).onSuccess(new Continuation<ReachableIP, Void>() {
第二個任務中會執行兩個任務,等兩個任務都執行完了才會往下執行,第三個任務可以擷取到上一個中的兩個任務的傳回值
兩個任務的具體聲明如下實現部分我去掉了,ReachableIP是自訂的class:
private Task<ReachableIP> getGatewayAsync() { return Task.callInBackground(new Callable<ReachableIP>() { @Override public ReachableIP call() throws Exception { return null; } });}private Task<ReachableIP> getRouterWanIpAsync() { return Task.callInBackground(new Callable<ReachableIP>() { @Override public ReachableIP call() throws Exception { return null; } });}
4). Exception處理
}, Task.BACKGROUND_EXECUTOR).continueWith(new Continuation<BindDeviceInfo, Void>() { @Override public Void then(Task<BindDeviceInfo> task) throws Exception { if (task.isFaulted()) { Exception exception = task.getError(); if (exception instanceof ResponseError) { ResponseError e = (ResponseError) exception; switch (e.errorCode()) { case ErrorCode.PASSWORD_ERROR: ...... break; default: break; } } } return null; } }, Task.UI_THREAD_EXECUTOR);
因為任務在哪裡有異常我們是可以預知到的,當有異常的時候,我們catch到再轉換為我們自己的異常在thorw出來如上面的ResponseError 是我們自訂的異常,這樣我們task.getError出來了可以做不同的處理。
Android 下的 bolts tasks