在上一篇Android架构实战(一)—— 核心思想中,我们已经对一种更清晰的安卓架构进行了一个概括性的了解,相信大家对其基本框架已经有所了解了。RxJava可以说是一种更清晰的安卓架构中一个非常核心的技术,它是连通各个层级直接的利器。RxJava在android开发中也越来越流行,它对降低耦合度,降低代码复杂性,增加可控性方面,有着非常大的作用。今天,我就来介绍一下我对RxJava的实用心得,以及学到的一些技巧。
一、基本介绍
多线程的操作对于一个Android程序来说是必不可少的,在发起网络请求,大量数据库操作,文件读取等耗时操作时,在其他线程执行任务能够降低用户对等待的时间的感知,使程序变得更加友好。众所周知,非UI线程是不允许对UI进行任何操作的,然而一个任务执行的结果往往是需要通过UI层面来进行展示的。为了解决这个问题,Android提供了消息队列的机制,即所谓的handler。
然而Handler的使用,无形中会带来许多问题。最明显的就是Message将一端逻辑代码生硬的分离开了,同时,如果Message类型过多的话,Handler内部的条件判断也随之增加,可读性大大降低。另外,在定义handler的时候,我们都会发现编译器给了这样一个警告:Handler classes should be static or leaks might occur。这是因为Handler如果定义成Activity的一个内部类,任意一个延时性的Message都会持有Handler的引用,而因为这个引用的存在,Handler无法被消除,从而导致Handler的外部类Activity也无法被回收。也就是说,如果消息队列中还存在未被处理的Message,而Activity却企图finish掉自己的话,程序就会crash了。(解决方式,网上都有讲解,一般都是通过static的Handler和弱应用来规避的)
二、基本介绍
public static void startDownload(Actvity actvity, final CallBack callBack) {
new Thread(new Runnable {
// 开始下载
Data data;
try{
data = getDataFromServer();
}catch(Exceptioni e){
callBack.onFail(e);
}
// 下载完成
activity.runOnUiThread(new Runnable() {
callBack.onSuccess(data):
});
}).start();
}
在Activity中发起线程,然后定义一个CallBack函数传递给方法,然后方法内部就开发发起网络请求了。如果想对这个任务做一些干预操作,就只能再提供一些其他的封装方法,或者提供更多的回调来实现了。在这个过程中,任务始终是以线程的方式存在的,只能够通过在工具类内部对其进行操作或者干预,维护成本和逻辑性都比较复杂。(当然,有许多网络请求库都已经对这些过程进行了封装,性能和易用性都很高,比如Volley)public static void getData() {
getDownloadObservable()
.subscribeOn(Schedulers.from(jobExecutor)) // 从线程池中获取线程
.observeOn(AndroidSchedulers.mainThread()) // 观察者的线程为主线程
.subscribe(new Subscriber<Data>()); // 自定义观察者
}
public static Observable<Data> getDownloadObservable() {
return Observable.create(new Observable.OnSubscribe<Data>() {
@Override
public void call(Subscriber<? super Data> subscriber) {
try {
subscriber.onNext(getDateFromServer()); // 数据接收
subscriber.onCompleted(); // 任务完成
} catch (Exception e) {
subscriber.onError(e); // 任务异常
}
}
});
}
当中的static函数可以看成是一个封装好的工具类。可以很明显的看到,需要执行的任务以Observable的形式被返回给主线程了。这样以来,对任务操纵的主动权就交还到调用者本身了。最基本的,在得到这个Observable后,就可以通过observeOn和subscribeOn这两个方法对任务和订阅者所在的线程进行任意的调配了(在示例中,我们自己提供了一个线程池,使得多个任务可以并发进行)。再比如,如果开发人员想要对任务的结果进行再次加工处理,则可以使用map/flatmap/filter等方法对Observable进行链式的操作。值得一提的是,链式的加工方法相当于流水线的效果,对于解耦方面的意义重大。而如果想要通过CallBack实现这种功能的化,就只能通过回调嵌套回调来进行了。
三、个人总结
附录
/**
* Decorated {@link java.util.concurrent.ThreadPoolExecutor}
*/
public class JobExecutor implements Executor {
private static final int INITIAL_POOL_SIZE = 3;
private static final int MAX_POOL_SIZE = 5;
// Sets the amount of time an idle thread waits before terminating
private static final int KEEP_ALIVE_TIME = 10;
// Sets the Time Unit to seconds
private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
private final BlockingQueue<Runnable> workQueue;
private final ThreadPoolExecutor threadPoolExecutor;
private final ThreadFactory threadFactory;
public JobExecutor() {
this.workQueue = new LinkedBlockingQueue<>();
this.threadFactory = new JobThreadFactory();
this.threadPoolExecutor = new ThreadPoolExecutor(INITIAL_POOL_SIZE, MAX_POOL_SIZE,
KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, this.workQueue, this.threadFactory);
}
@Override public void execute(Runnable runnable) {
if (runnable == null) {
throw new IllegalArgumentException("Runnable to execute cannot be null");
}
this.threadPoolExecutor.execute(runnable);
}
private static class JobThreadFactory implements ThreadFactory {
private static final String THREAD_NAME = "android_";
private int counter = 0;
@Override public Thread newThread(Runnable runnable) {
return new Thread(runnable, THREAD_NAME + counter);
}
}
}