RxJava執行緒切換代替Thread和Handler
阿新 • • 發佈:2019-01-23
在我們的日常開發中,我們可能會經常涉及到執行緒的切換,比如:需要在子執行緒中載入資料庫中的資料,一般情況下,我們會這樣做:
new Thread(new Runnable() {
@Override
public void run() {
//do something
}
}).start();
高效一點的會用執行緒池來實現。但是有一種情況下是很麻煩的-子執行緒和主執行緒有執行順序或者有互動的時候,這時候我們一般藉助Handler機制來實現或者呼叫Activity的runOnUiThread(new Runnable(){})
子執行緒執行
定義一個子執行緒執行的任務介面
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的部落格