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

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

期望

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

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

框架的设计:

image.png

Async类

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

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

     }

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

Subscribe

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

public interface Subscriber<T> {
    
    
    void onError(Throwable th);

    void onSuccess(T t);
}

SubscriberForSuccess

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

public abstract class SubscriberForSuccess<T> implements Subscriber<T> {
    
    

    @Override
    public void onError(Throwable th) {
    
    
        th.printStackTrace();
    }
}

Async.create(()-> 1 + 1).observableOnMain(new SubscriberForSuccess<Integer>() {
    
    
    @Override
    public void onSuccess(Integer data) {
    
    
        System.out.println("data: " + data);
    }
});

Scheduler

线程调度器接口

public interface Scheduler {
    
    
    void execute(Runnable runnable);
     ExecutorService getExecutor();
}

Schedulers

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

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. 对线程的状态进行重置
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;
    }
}

使用


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());
    }
}

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题

图片

猜你喜欢

转载自blog.csdn.net/Androiddddd/article/details/135430906