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/
- Bolts介绍
- bolts-android
- Bolts-Android
- [LintCode] Nuts and Bolts
- 事务处理的nuts和bolts
- Android 下的 bolts tasks
- facebook开源库-Bolts中文文档
- uva 11138 - Nuts and Bolts(二分匹配)
- UVa11138 - Nuts and Bolts(二分匹配)
- [译]【Storm入门指南】第五章 Bolts
- Storm入门之第五章Bolts
- 题目:nuts 和 bolts 的问题
- 【Storm入门指南】第五章 Bolts
- R Programming: Part 1 - Nuts and Bolts
- framework not found Bolts for architecture x86_64
- bolts全收集流程攻略解析
- lintcode(399)Nuts 和 Bolts 的问题
- 399.Nuts & Bolts Problem-Nuts 和 Bolts 的问题(中等题)
- 正则
- T-SQL中的APPLY用法(半翻译)
- Android 安全方面知识汇总
- 使用接口解决JS文件冲突
- eclipse 添加server、svn
- Bolts介绍
- git 常用命令
- Dijkstra算法解决最短路径问题
- jsp 页面实现局部打印功能与全局打印
- 程序员的自我修炼
- Android图形---硬件加速(Hardware Acceleration)(二)
- Oracle中的索引详解
- ArcGIS教程:填挖方的工作原理
- Redis 2.8 配置文件说明