Android子線程切換到UI線程方法總結

線程切換

經過消息發送(發佈)和接收(訂閱)的方式切換的。java

1 .Handler

子線程(非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

  • 1 . Handler機制與Activity生命週期不一致的緣由,容易致使內存泄漏。
  • 2 . 實例化 handler
//實例化handler在其餘線程的時候要下面這樣寫(UI線程內部已經實現,無需寫)
 private Handler handler = new Handler(Looper.getMainLooper());
複製代碼
2. Activity.runOnUiThread

用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();
複製代碼
3. View.post(Runnable r)

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線程中執行。

4. AsyncTask

內部就是一個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());
        }
    }
複製代碼
5. Rxjava

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();
                    }
                });
    }
複製代碼
相關文章
相關標籤/搜索