一款简单高效的Android异步框架

当我们在用java进行Android开发时,经常会涉及到线程间的切换操作。由子线程执行耗时任务,执行完毕后再切到主线程。对于这种需求在Rxjava出现之前不可避免采用handler.post(runnable)来实现。后来Rxjava出现了,我们便可以借助于RxJava强大的操作符subscribeOn, observeOn来实现线程的切换。在梳理以前用Rxjava开发的项目,发现其实很多时候都是用它来进行线程切换。而对于开发来讲,Rxjava框架比较重,如果仅仅是想方便的进行线程切换,完全没有必要引入Rxjava。为此,我们可以自己封装一套框架,实现这个功能。

期望

我们期望框架能够支持如下功能:

  1. 简单方便进行线程的切换(必须的)
  2. 最好能像Rxjava那样使用,因为大多数人已经用惯了
  3. 线程池也可以提供给外部使用
  4. 功能尽量单一,代码简洁

框架的设计:

Async类

框架的入口,相关方法命名和Rxjava类似,用途也一致,不做过多讲述。新增了一个 observableOnMain 方法,是针对线程执行耗时操作后将结果返回给主线程的场景。使用如下:

java 复制代码
Async.create(()-> 1 + 1).observableOnMain(new Subscriber<Integer>() {
     @Override
     public void onError(Throwable th) {

     }

     @Override
     public void onSuccess(Integer data) {
         printData(data);
     }
 })

Subscribe

这是一个接口,其实现也非常简单

java 复制代码
public interface Subscriber<T> {
    void onError(Throwable th);

    void onSuccess(T t);
}

SubscriberForSuccess

这个类存在的目的是为了针对这种场景:我们在子线程中执行了任务,但只关注任务执行成功的情况,不想搭理失败。

java 复制代码
public abstract class SubscriberForSuccess<T> implements Subscriber<T> {

    @Override
    public void onError(Throwable th) {
        th.printStackTrace();
    }
}
java 复制代码
Async.create(()-> 1 + 1).observableOnMain(new SubscriberForSuccess<Integer>() {
    @Override
    public void onSuccess(Integer data) {
        System.out.println("data: " + data);
    }
});

Scheduler

线程调度器接口

java 复制代码
public interface Scheduler {
    void execute(Runnable runnable);
     ExecutorService getExecutor();
}

Schedulers

相当于线程调度器的 provider, 里面提供了 io, computation, main 三种类型的调度器

java 复制代码
public class Schedulers {
    static final int CPU = Runtime.getRuntime().availableProcessors();
    public static final class IOScheduler implements Scheduler {
        /**
         * 核心线程数:通常可以将核心线程数设置为0, IO线程池不需要响应的及时性,所以将常驻线程设置为0,可以减少应用的线程数量
         * 最大线程数:通常中小型,业务比较简单设置成64即可。
         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(0, 64, 1,
                TimeUnit.MINUTES, new SynchronousQueue<>(), new MobileThreadFactory("IOScheduler"));
        @Override
        public void execute(Runnable runnable) {
            executor.execute(runnable);
        }
        public ExecutorService getExecutor() {
            return executor;
        }
    }

    private static final class ComputationScheduler implements Scheduler {
        /**
         * 核心线程:将核心线程数设置为该手机的 CPU 核数,理想状态下每一个核可以运行一个线程,这样能减少 CPU 线程池的调度损耗又能充分发挥 CPU 性能。
         * 最大线程数:和核心线程保持一致,因为当最大线程数超过了核心线程数时,反倒会降低 CPU 的利用率,因为此时会把更多的 CPU 资源用于线程调度上,
         */
        ExecutorService executor = new ThreadPoolExecutor(Schedulers.CPU, Schedulers.CPU, 1,
                TimeUnit.MINUTES, new LinkedBlockingDeque<Runnable>(),  new MobileThreadFactory("ComputationScheduler"));

        @Override
        public void execute(Runnable runnable) {
            executor.execute(runnable);
        }

        @Override
        public ExecutorService getExecutor() {
            return executor;
        }
    }
    private static class IOSchedulerHolder {
        private static final IOScheduler INSTANCE = new IOScheduler();
    }
    public static Scheduler io() {
        return IOSchedulerHolder.INSTANCE;
    }
    private static class ComputationSchedulerHolder {
        private static final ComputationScheduler INSTANCE = new ComputationScheduler();
    }
    public static Scheduler computation() {
        return ComputationSchedulerHolder.INSTANCE;
    }

    private static class MainSchedulerHolder {
        private static final Main INSTANCE = new Main();
    }
    public static Scheduler main() { return MainSchedulerHolder.INSTANCE;}

    private static class Main implements Scheduler {
        @Override
        public void execute(Runnable runnable) {
             Platform.get().execute(runnable);
        }

        @Override
        public ExecutorService getExecutor() {
            return null;
        }
    }
}

MobileThreadFactory

自定义 ThreadFactory, 做了如下配置:

  1. 对线程名字进行标识,方便跟踪。
  2. 修改线程栈,可一定程度节省虚拟内存
  3. 对线程的状态进行重置
java 复制代码
public class MobileThreadFactory implements ThreadFactory {
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    public MobileThreadFactory(String name) {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                Thread.currentThread().getThreadGroup();
        namePrefix = name + "-pool-" +
                poolNumber.getAndIncrement() +
                "-thread-";
    }

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r,
                namePrefix + threadNumber.getAndIncrement(),
                -512 * 1024);
        if (t.isDaemon()) {
            t.setDaemon(false);
        }
        if (t.getPriority() != Thread.NORM_PRIORITY) {
            t.setPriority(Thread.NORM_PRIORITY);
        }
        return t;
    }
}

使用

java 复制代码
public class AsyncActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async);
        initView();
    }

    private void initView() {
        findViewById(R.id.btn_async).setOnClickListener(v -> Async.create(() -> 1 + 1).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).subscribe(new Subscriber<Integer>() {
            @Override
            public void onError(Throwable th) {

            }

            @Override
            public void onSuccess(Integer data) {
                printData(data);
            }
        }));
        findViewById(R.id.btn_async_main).setOnClickListener(v -> Async.create(()-> 1 + 1).observableOnMain(new Subscriber<Integer>() {
            @Override
            public void onError(Throwable th) {

            }

            @Override
            public void onSuccess(Integer data) {
                printData(data);
            }
        }));
        findViewById(R.id.btn_async_success).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Async.create(()-> 1 + 1).observableOnMain(new SubscriberForSuccess<Integer>() {
                    @Override
                    public void onSuccess(Integer data) {
                     printData(data);
                    }
                });
            }
        });
        findViewById(R.id.btn_thread_pool).setOnClickListener(v -> {
            for (int i = 0; i < 10; i ++) {
                Schedulers.io().execute(() -> {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println("execute on:" + Thread.currentThread().getName());
                });
            }
        });

    }
    private void printData(Integer data) {
        System.out.println("data: " + data + "   threadName:" + Thread.currentThread().getName());
    }
}
相关推荐
2402_8575893622 分钟前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
吾爱星辰1 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer1 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
哎呦没1 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch2 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
编程、小哥哥2 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
IT学长编程3 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
韩楚风3 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
莹雨潇潇3 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
网络研究院3 小时前
Android 安卓内存安全漏洞数量大幅下降的原因
android·安全·编程·安卓·内存·漏洞·技术