1. 程式人生 > >Handler傳送訊息,週期性更新UI總結

Handler傳送訊息,週期性更新UI總結

1.Handler的作用

handler是用於執行緒間傳送訊息和處理訊息的。

2.Handler傳送訊息的方式

1.最常用的方式是:
handler.sendMessage()、handler.sendEmptyMessage()、handler.sendMessageAtTime()、handler.sendMessageDelayed()等方法都是將訊息傳送到handler自己,它們的區別就是傳送訊息時是否延時,然後通過handler重寫的handleMessage方法來處理。
在onCreate方法中,開啟一個子執行緒,處理耗時操作,然後傳送訊息給handler處理,程式碼如下:

new Thread(new Runnable() {
            @Override
            public void run() {
            //耗時操作 ...
                mHandle.sendEmptyMessage(1);
            }
        }).start();

然後在handler例項化時,重寫handleMessage方法,處理子執行緒發過來的訊息:

private Handler mHandle = new Handler(){
        @Override
        public
void handleMessage(Message msg) { switch (msg.what){ case 1: tvHandler.setText("handler.sendMessage" +1); break; default: break; } } };

2.handler.post(myRunnable)+runnable的方式處理
handler.post(myRunnable)、
handler.postDelayed(myRunnable,time)等方法,將訊息交給runnable處理

mHandlerRunnable.postDelayed(myRunnable,1000);

定義handler和runnable

private Handler mHandlerRunnable = new Handler();
    private Runnable myRunnable = new Runnable() {
        @Override
        public void run() {
            tvRunnable.setText("runnable+handle.postdelayer"+1);
        }
    };

其實通過閱讀原始碼發現,系統將runnable介面包裝成Message,最終還是呼叫handler.sendMessage的方式處理。
3.通過runOnUiThread(new Runnable)的方式處理

private void updateUI(){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tvRunOnUi.setText("runOnUiThread"+1);
            }
        });
    }

4.通過view.post(new Runnable)的方式處理

private void viewPost(){
        tvViewPost.post(new Runnable() {
            @Override
            public void run() {
                tvViewPost.setText("viewPost"+1);
            }
        });
    }

如圖所示,看四種方法更新四個textview的效果:
這裡寫圖片描述

3.用handler週期性的更新UI

通過handler.sendMessage的方式與TimerTask配合,週期性更新UI

Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                myHandlerTimeTask.sendEmptyMessage(1);
            }
        };
        timer.schedule(task,0,1000);
private Handler myHandlerTimeTask = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            tvTimeTask.setText("runnable+handle.postdelayer+timeTask"+title);
            title++;
        }
    };

大家感興趣的話,也可以嘗試用handler.post(runnable)的方式週期性更新UI,注意用runnable,需要在onDestroy方法中呼叫mHandlerRunnable.removeCallbacks(myRunnable);
看效果圖:
這裡寫圖片描述

完整程式碼如下:
佈局檔案,一個LinearLayout,五個textview

activity程式碼:
package com.hw.yjg.testview;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import java.util.Timer;
import java.util.TimerTask;

public class HandleDemoActivity extends AppCompatActivity {

    private TextView tvHandler;
    private TextView tvRunnable;
    private TextView tvRunOnUi;
    private TextView tvViewPost;
    private TextView tvTimeTask;
    private int title = 0;

    //handleMessage + handler.sendMessage
    private Handler mHandle = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 1:
                    tvHandler.setText("handler.sendMessage" +1);
                    break;
                default:
                    break;
            }
        }
    };

    //Runnable + Handler.postDelayed(runnable,time)
    private Handler mHandlerRunnable = new Handler();
    private Runnable myRunnable = new Runnable() {
        @Override
        public void run() {
            tvRunnable.setText("runnable+handle.postdelayer"+1);
        }
    };

    private void updateUI(){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tvRunOnUi.setText("runOnUiThread"+1);
            }
        });
    }

    private void viewPost(){
        tvViewPost.post(new Runnable() {
            @Override
            public void run() {
                tvViewPost.setText("viewPost"+1);
            }
        });
    }

    //Handler.sendMessage+TimerTask
    private Handler myHandlerTimeTask = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            tvTimeTask.setText("handle.sendMessage+timerTask"+title);
            title++;
        }
    };   

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handle_demo);

        tvHandler = (TextView) findViewById(R.id.tvHandler);
        tvRunnable = (TextView) findViewById(R.id.tvRunnable);
        tvRunOnUi = (TextView) findViewById(R.id.tvRunOnUiThread);
        tvViewPost = (TextView) findViewById(R.id.tvViewPost);
        tvTimeTask = (TextView) findViewById(R.id.tvTimeTask);

        //1.子執行緒+handleMessage
        new Thread(new Runnable() {
            @Override
            public void run() {
                mHandle.sendEmptyMessage(1);
            }
        }).start();

        //2.handler.post(myRunnable)+runnable
        mHandlerRunnable.postDelayed(myRunnable,1000);

        //3.runOnUiThread
        updateUI();

        //4.view.post(new Runnable)
        viewPost();

        /*Timer timer = new Timer();
        timer.scheduleAtFixedRate(new MyTask(),0,500);*/

        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                myHandlerTimeTask.sendEmptyMessage(1);
            }
        };
        timer.schedule(task,0,1000);       
    }
    @Override
    protected void onDestroy() {
        mHandlerRunnable.removeCallbacks(myRunnable);
        super.onDestroy();
    }
}