Android级连异步任务——Bolts-Android原理简介-阿里云开发者社区

开发者社区> xiaxueliang> 正文

Android级连异步任务——Bolts-Android原理简介

简介: Parse开源了一个面向iOS和Android的底层库集合,统称为Bolts。根据Parse的公告,Bolts是Parse和Facebook共同努力将两家公司各自独立开发的小型底层工具类合并的结果。Bolts-Android为一个级联的异步任务。
+关注继续查看

Parse开源了一个面向iOS和Android的底层库集合,统称为Bolts。根据Parse的公告,Bolts是Parse和Facebook共同努力将两家公司各自独立开发的小型底层工具类合并的结果。Bolts-Android为一个级联的异步任务。

Bolts-Android github地址:
https://github.com/BoltsFramework/Bolts-Android

本文案例的 github地址:
https://github.com/xiaxveliang/Android_ThirdSource_Bolts

原理解析:

  • 级连异步任务,可按以下方式使用
Task.call(new Callable<Boolean>() {
    @Override
    public Boolean call() throws Exception {
        // 异步线程
        return true;
    }
}, Task.BACKGROUND_EXECUTOR).continueWith(new Continuation<Boolean, Object>() {
    @Override
    public Object then(Task<Boolean> task) throws Exception {
        // 异步线程
        return null;
    }
}, Task.BACKGROUND_EXECUTOR).continueWith(new Continuation<Object, Boolean>() {
    @Override
    public Boolean then(Task<Object> task) throws Exception {
        // UI线程
        return true;
    }
}, Task.UI_THREAD_EXECUTOR);
  • 可自定义线程池,来处理不同类型的任务

例如,我们除了有Task.BACKGROUND_EXECUTOR线程池,还可以有 NETWORK_EXECUTOR(只处理网络请求)、DISK_EXECUTOR(只处理Sdcard的读写)等线程池。

  • 可通过Task类waitForCompletion()方法,阻塞当前线程,直到Task任务运行结束
  • 每一个Task类的对象,均包含一个Continuation列表,用来管理当前Task对象全部的Continuation任务
    // 每一个Task对象都有一个自己的Continuation队列(continuations非全局,这样不同task的continuation就不会混淆)
    private List<Continuation<TResult, Void>> continuations = new ArrayList<>();
  • Continuation任务的执行时机

当前Task对象的call()方法运行结束后,会调用trySetResult()方法,将运行结果保存下来;并循环执行continuations列表中的任务。
Task.java类中trySetResult方法:

    //当前task,执行结束后的返回数据赋值
    //Sets the result on the Task if the Task hasn't already been completed.
    boolean trySetResult(TResult result) {
        synchronized (lock) {
            // 任务运行结束判断
            if (complete) {
                return false;
            }
            // 任务运行结束
            complete = true;
            // 任务结果赋值
            Task.this.result = result;
            // 唤醒lock wait等待(如果之前调用过waitForCompletion阻塞线程,那么此处会被唤醒)
            lock.notifyAll();
            // 循环执行continuations任务
            runContinuations();
            return true;
        }
    }

Task.java类中runContinuations方法:

//循环执行continuations任务
//问题: Continuation并没有区分执行线程呀?
//答:每一个Continuation又是一个封装的Continuation.then(),方法中将任务提交到的不同线程池
private void runContinuations() {
    synchronized (lock) {
        // 循环运行当前continuations列表任务
        for (Continuation<TResult, ?> continuation : continuations) {
            try {
               // 执行Continuation任务
                continuation.then(this);
           } catch (RuntimeException e) {
                throw e;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
       }
        // 当前Task的continuations队列置空
       continuations = null;
    }
}

问题:continuations如何将不同任务提交到不用的线程池呢???
答:每一个Continuation又是一个封装的Continuation.then(),方法中将任务提交到的不同线程池

Task.java类中continueWith方法:

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

    // 上次task的完成情况
    boolean completed;
    // 构建一个新的task
    final TaskCompletionSource<TContinuationResult> tcs = new TaskCompletionSource<>();
    //
    synchronized (lock) {
        // 上次task的完成情况
        completed = this.isCompleted();
        // 如果上次task 未完成,添加到task列表
        if (!completed) {
            // 向continuations队列中添加一个“需提交到不同线程池执行的task任务”
            this.continuations.add(new Continuation<TResult, Void>() {
                @Override
                public Void then(Task<TResult> task) {
                    //
                    completeImmediately(tcs, continuation, task, executor, ct);
                    return null;
                }
            });
        }
    }
    // 上次任务完成,当前线程执行
    if (completed) {
        completeImmediately(tcs, continuation, this, executor, ct);
    }
    //
    return tcs.getTask();
}

这里可以看出每次提交的Continuation任务中,均封装了一个completeImmediately(tcs, continuation, task, executor, ct);来确定其运行的线程池等信息。

= THE END =

文章首发于公众号”CODING技术小馆“,如果文章对您有帮助,欢迎关注我的公众号。
文章首发于公众号”CODING技术小馆“,如果文章对您有帮助,欢迎关注我的公众号。
文章首发于公众号”CODING技术小馆“,如果文章对您有帮助,欢迎关注我的公众号。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
10089 0
使用NAT网关轻松为单台云服务器设置多个公网IP
在应用中,有时会遇到用户询问如何使单台云服务器具备多个公网IP的问题。 具体如何操作呢,有了NAT网关这个也不是难题。
26794 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13892 0
windows server 2008阿里云ECS服务器安全设置
最近我们Sinesafe安全公司在为客户使用阿里云ecs服务器做安全的过程中,发现服务器基础安全性都没有做。为了为站长们提供更加有效的安全基础解决方案,我们Sinesafe将对阿里云服务器win2008 系统进行基础安全部署实战过程! 比较重要的几部分 1.
9161 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
4660 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
4508 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
7365 0
+关注
xiaxueliang
一名普通Android程序员,专注Android、OpenGL ES、移动音视频等终端技术研发。希望通过该博客分享自己的Coding学习笔记。
36
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载