經過消息發送(發佈)和接收(訂閱)的方式切換的。java
子線程(非UI線程)調用handler對象sendMessage(msg)方法,將消息發送給關聯Looper,Looper將消息存儲在MessageQueue消息隊列裏面。安全
而後輪巡取出MessageQueue中的消息給UI線程中handler處理,handler獲得消息調用handleMessage方法處理消息,從而能夠更新Ui。bash
private Handler handler2=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:
//UI線程
textView.setText(msg.obj.toString());
}
}
};
//開啓線程執行耗時操做
new Thread(){
@Override
public void run() {
//執行相關耗時操做等等...
//休眠3s
sleep(3000);
Message message = new Message();
//區分標誌
message.what=1;
//傳參到ui線程
message.obj=123123;
handler2.sendMessage(message);
}
}.start();
複製代碼
** 擴展注意:**ide
//實例化handler在其餘線程的時候要下面這樣寫(UI線程內部已經實現,無需寫)
private Handler handler = new Handler(Looper.getMainLooper());
複製代碼
用Activity對象的runOnUiThread方法更新,在子線程中經過runOnUiThread()方法更新UIoop
new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
複製代碼
View.post(Runnableaction),View得到當前線程(即UI線程)的Handler,而後將action對象post到Handler裏。post
在Handler裏,它將傳遞過來的action對象包裝成一個Message(Message的callback爲action),而後將其投入UI線程的消息循環中。ui
在Handler再次處理該Message時,直接調用runnable的run方法。而此時,已經路由到UI線程裏,所以,咱們能夠毫無顧慮的來更新UI。spa
new Thread(){
@Override
public void run() {
super.run();
for (int i=0;i<3;i++){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
tv.post(new Runnable() {
@Override
public void run() {
tv.setText("經過View.post(Runnable r) 方法");
}
});
}
}.run();
複製代碼
擴展注意:線程
子線程能不能更新UI,答案是確定的。具體閱讀下這篇文章:Android 子線程更新UI?code
上面就是爲了實現用一個Thread來更新tv,能夠實現這個功能,刷新UI界面。可是這樣是不對的,由於它違背了單線程模型:Android UI操做並非線程安全的而且這些操做必須在UI線程中執行。
內部就是一個Handler和線程池的封裝。在線程池中執行後臺任務,並在執行過程當中將執行進度傳遞給主線程,當任務執行完畢後,將最終結果傳遞給主線程。
private class MyAsyncTask extends AsyncTask{
//第一階段————準備階段
@Override
protected void onPreExecute() {
super.onPreExecute();
}
//第二階段————耗時操做
@Override
protected Object doInBackground(Object[] objects) {
for (int i=0;i<3;i++){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return objects[0].toString();
}
//第三階段———— 更新UI
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
tv.setText(o.toString());
}
}
複製代碼
RXJAVA的實現,是一種擴展式的觀察者模式。
RXJAVA中有四種概念。observable(被觀察者),observer(觀察者),subscribe(訂閱),事件。
Observable和Observer經過subscribe來實現訂閱關係。
與傳統的觀察者模式不一樣,除了onNext事件外,rxjava還提供了onCompleted和onError。當再也不有onNext事件發送時,將以onCompleted事件做爲結束。當處理過程當中出現異常時,會觸發onError,同時隊列自動終止,不容許再有事件發出。onCompleted和onError在一個序列中有且只有一個,兩者互斥,只能出現一個。
源碼來自:RxJava線程切換代替Thread和Handler
public static <T> void doTask(final Task<T> task) {
//建立被觀察者 Observable,它決定何時觸發事件以及觸發怎樣的事件。
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) {
//主線程更新UI
// task.doOnUIThread();
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
}
複製代碼