Bolts介绍

来源:互联网 发布:联排和双拼的区别 知乎 编辑:程序博客网 时间:2024/06/07 20:06

bolt是Parse和facebook开发的一个供内部使用的底层小工具集合,目前主要包括两方面的内容:
- “Tasks”,可以方便组织管理一系列复杂的异步任务代码,是对Javascript Promise模型的模仿。
- 提供一种App Links protocol的实现,帮助你链接到其他App中的内容和处理传入的deep-links。
本文只介绍Task部分。

官方定义:
A task represents an asynchronous operation. Typically, a Task is returned from an asynchronous function and gives the ability to continue processing the result of the task. When a task is returned from a function, it’s already begun doing its job. A task is not tied to a particular threading model: it represents the work being done, not where it is executing.
简单翻译:
一个任务表示异步操作。通常,一个任务是从一个异步函数返回,并给出了继续处理任务的结果的能力。当任务从一个函数返回时,它就已经开始做它的工作了。一个任务不是和一个特定的线程模型联系在一起:它代表了正在做的工作,而不是在执行的地方。

优点:
- 占用更少的系统资源,因为不会再等待其他任务时阻塞线程。
- 连续执行数个任务不会像只使用回调函数时那样创建嵌套的“金字塔(pyramid)”代码。
- Tasks是完全可组合的,允许开发人员执行分支、并行和复杂的错误处理。
- 开发人员可以按照执行顺序安排基于任务的代码,而不必将逻辑分解到分散的回调函数中。
常用函数:

  • Task.call和Task.callInBackground

该函数会在相关线程执行完任务后返回一个Task来标记任务的执行情况。

  • continueWith和continueWithTask

该函数会在当前task完成后调用Continuation.then方法,可以在该方法查看task是否成功,并获取其返回值。如果需要根据前一个的task返回状态来进行新的异步操作,可以使用continueWithTask方法来代替continueWith,该方法会返回一个新的task,除非新的task完成,否则continueWithTask返回的task也不会变成完成状态,通过这个可以有效的避免多重嵌套。

  • onSuccess和onSuccessTask

多数情况下,只有当前一个task完成你才会做后面的工作,该方法可以帮你先忽略不成功的任务,你可以在后面集中处理它们。

串行任务
一个任务接起前一个任务,只有当前一个任务执行完后,后一个任务才会执行。

Task.call(new Callable<Integer>() {            @Override            public Integer call() throws Exception {                Bitmap bm = cacheMap.get(p);                if (bm != null) {                    iv.setImageBitmap(bm);                    return SUCCESS;                } else {                    iv.setImageResource(R.drawable.default_img);                }                return FAIL;            }        }).onSuccessTask(new Continuation<Integer, Task<Bitmap>>() {            @Override            public Task<Bitmap> then(Task<Integer> task) throws Exception {                int ret = task.getResult();                if (ret == SUCCESS) {                    Log.d(TAG, "task finish");                    return Task.cancelled();                } else {                    synchronized (iv) {                        iv.setTag(p);                    }                    return asyncDecodeTask(p);                }            }        }).onSuccessTask(new Continuation<Bitmap, Task<Bitmap>>() {            @Override            public Task<Bitmap> then(Task<Bitmap> task) throws Exception {                final Bitmap bm = task.getResult();                if (bm != null) {                    synchronized (iv) {                        if (((String) iv.getTag()).equals(p)) {                            iv.setImageBitmap(bm);                        } else {                            Log.d(TAG, "has scroll over");                        }                    }                    return Task.cancelled();                } else {                    return asyncDownloadTask(p);                }            }        }, Task.UI_THREAD_EXECUTOR).onSuccessTask(new Continuation<Bitmap, Task<Integer>>() {            @Override            public Task<Integer> then(Task<Bitmap> task) throws Exception {                Bitmap bm = task.getResult();                if (bm != null) {                    asyncWriteTask(bm, p);                    synchronized (iv) {                        if (((String) iv.getTag()).equals(p)) {                            iv.setImageBitmap(bm);                        } else {                            Log.d(TAG, "has scroll over");                        }                    }                    return Task.cancelled();                } else {                    return Task.forResult(ERROR);                }            }        }, Task.UI_THREAD_EXECUTOR).continueWith(new Continuation<Integer, Object>() {            @Override            public Object then(Task<Integer> task) throws Exception {                if (task.isFaulted()) {                    Log.i(TAG, "error log " + task.getError().getMessage());                }                if(task.isCancelled()){                    Log.i(TAG, "has cancelled");                }                int ret = task.getResult();                Log.d(TAG, "ret" + ret);                return null;            }        });

上面是一段异步加载图片的代码,先从缓存中获取,拿不到就尝试从磁盘中获取,再拿不到就从上网络下载,以上只要某一步成功就会取消的后续任务,错误会在最后统一处理。
- 并行任务
如果需要多任务同时进行,要使用whenAll函数,传入一个任务列表。

Task.callInBackground(new Callable<Integer>() {            @Override            public Integer call() throws Exception {                Log.d(TAG, "start download");                URL url = new URL(FILE_URL);                HttpURLConnection conn = (HttpURLConnection) url.openConnection();                conn.setRequestMethod("GET");                conn.setConnectTimeout(5000);                int code = conn.getResponseCode();                Log.d(TAG, "code " + code);                if (code == 200) {                    int length = conn.getContentLength();                    Log.d(TAG, "length" + length);                    RandomAccessFile raf = new RandomAccessFile(FILE_NAME, "rwd");                    //指定创建的这个文件的长度                    raf.setLength(length);                    capture.set(length);                    raf.close();                    return SUCCESS;                }                return FAIL;            }        }).onSuccessTask(new Continuation<Integer, Task<Void>>() {            @Override            public Task<Void> then(Task<Integer> task) throws Exception {                List<Task<Void>> lst = new ArrayList<Task<Void>>();                if (task.getResult() == SUCCESS) {                    int length = capture.get();                    int blockSize = length / THREAD_COUNT;                    for (int i = 0; i < THREAD_COUNT; i++) {                        if (i == THREAD_COUNT - 1) {                            lst.add(asyncDownload(i * blockSize, capture.get(), FILE_URL, FILE_NAME));                        } else                            lst.add(asyncDownload(i * blockSize, (i + 1) * blockSize, FILE_URL, FILE_NAME));                    }                }                return Task.whenAll(lst);            }        }).continueWith(new Continuation<Void, Object>() {            @Override            public Object then(Task<Void> task) throws Exception {                if (task.isFaulted()) {                    Log.e(TAG, task.getError().getMessage());                }                if(task.isCompleted())                    Log.d(TAG, "finish task!");                return null;            }        });

上面是一段多线程并行分片下载同一个文件的代码,只有当所有的任务全部完成后whenAll的返回值才会变成完成状态,capture是bolts提供的简单泛型封装,允许你在task之间传递数据。
个人理解:
Continuation相当于控制器,应该在Continuation.then中控制调用不同的task,根据返回的task来判断任务执行情况,但实际情况难免有些不同,也可以灵活变通,在then中写业务逻辑。
总结一下,task能方便的帮我们组织和管理异步操作的代码,有效解决回调嵌套问题,使代码结构清晰,但因为java是强类型语言,函数返回值单一,没有javascript灵活,bolts中广泛采用泛型,函数的返回值处理会比较麻烦。本文只是简单介绍,如果想详细了解Bolts和Promise异步编程模型可以参看下面的网站。

以上均是本人的个人理解,如有错误, 欢迎指正!

相关资料:
https://github.com/BoltsFramework/Bolts-Android

http://www.infoq.com/cn/news/2014/02/parse-announces-bolts

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

https://www.promisejs.org/

0 0
原创粉丝点击