Android 下的 bolts tasks
本文主要介绍的是在Android 下使用 bolts tasks, bolts tasks 可以很方便的让我们将一些异步task关联起来执行。让这些tasks有顺序的执行(当我们一个task的执行要基于另一个task的时候)。
-
github 地址 Bolts-Android
-
gradle中引用
dependencies { compile 'com.parse.bolts:bolts-android:1.2.0' }
- 具体的使用
(我也是初学者,只是偶尔用过一次。理解的也很简单,我只是列出这个库里面我用到的一些方法,望见谅)
既然是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出来了可以做不同的处理。
- 总结
我自己也是新手,我只是偶尔在项目中用到了Blots Task的库,我只是列举了一些非常简单的我用到的方法,其实还有很多方法我没用到。希望大家共同进步。