在我们的日常开发中,我们可能会经常涉及到线程的切换,比如:需要在子线程中加载数据库中的数据,一般情况下,我们会这样做:
new Thread(new Runnable() {
@Override
public void run() {
//do something
}
}).start();
高效一点的会用线程池来实现。但是有一种情况下是很麻烦的-子线程和主线程有执行顺序或者有交互的时候,这时候我们一般借助Handler机制来实现或者调用Activity的runOnUiThread(new Runnable(){})
。但是今天我们来介绍一种利用RxJava实现的主线程、子线程快速切换的方法。
子线程执行
定义一个子线程执行的任务接口
public interface IOTask<T> {
void doOnIOThread();
}
在RxScheduler中定义一个在doOnIOThread
方法,利用observeOn
来切换执行的线程
public static <T> void doOnIOThread(final IOTask<T> task) {
Observable.just(task)
.observeOn(Schedulers.io())
.subscribe(new Action1<IOTask<T>>() {
@Override
public void call(IOTask<T> tioTask) {
tioTask.doOnIOThread();
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
}
主线程执行
同理,如果想在主线程中执行时,定义一个任务类接口UITask
public interface UITask<T> {
void doOnUIThread();
}
在RxScheduler中定义一个在doOnUiThread
方法:
public static <T> void doOnUiThread(final UITask<T> task) {
Observable.just(task)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<UITask<T>>() {
@Override
public void call(UITask<T> tuiTask) {
task.doOnUIThread();
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
}
主线程和子线程有交互执行
这种情况比较复杂些,一般是在子线程中执行完后,需要在主线程中执行一些代码,有着一定的时间顺序关系。但是无论怎么变化,RxJava都能轻松搞定~~
定义一个任务抽象类Task
,其中T
表示子线程和主线程需要调用的对象
public abstract class Task<T> {
private T t;
public Task(T t) {
this.t = t;
}
public void setT(T t) {
this.t = t;
}
public T getT() {
return t;
}
public abstract void doOnUIThread();
public abstract void doOnIOThread();
}
在RxScheduler
类中定义一个doTask
方法:
public static <T> void doTask(final Task<T> task) {
Observable.create(new Observable.OnSubscribe<T>() {
@Override
public void call(Subscriber<? super T> subscriber) {
task.doOnIOThread();
subscriber.onNext(task.getT());
subscriber.onCompleted();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<T>() {
@Override
public void call(T t) {
task.doOnUIThread();
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
}
原理很简单,如果你熟悉RxJava的使用的话~
测试代码
RxScheduler.doOnIOThread(new IOTask<Void>() {
@Override
public void doOnIOThread() {
System.out.println("doOnIOThread->" + Thread.currentThread().getName());
}
});
RxScheduler.doOnUiThread(new UITask<Void>() {
@Override
public void doOnUIThread() {
System.out.println("doOnUIThread->" + Thread.currentThread().getName());
}
});
final List<String> mData = new ArrayList<>();
RxScheduler.doTask(new Task<List<String>>(mData) {
@Override
public void doOnUIThread() {
for (String i : mData) {
System.out.println(Thread.currentThread().getName() + "-->" + i);
}
}
@Override
public void doOnIOThread() {
mData.add("java");
mData.add("hello");
System.out.println(Thread.currentThread().getName() + "-->" + mData.size());
}
});
结果如下:
shiyiliang.me.langelibarysample I/System.out: doOnIOThread->RxIoScheduler-2
shiyiliang.me.langelibarysample I/System.out: RxIoScheduler-2-->2
shiyiliang.me.langelibarysample I/System.out: doOnIOThread->main
shiyiliang.me.langelibarysample I/System.out: main-->java
shiyiliang.me.langelibarysample I/System.out: main-->hello
是不是比使用Thread或者线程池方便多了,虽然内部底层原理类似,但是后者使用起来就方便多了。
如果想阅读其他的文章,可以访问我的个人博客Lange的博客