Handler使用大全

Handler是什麼

handler是Android給我們提供用來更新UI的一套機制,也是一套消息處理機制,我們可以發消息,也可以通過它處理消息


原理(解析異步消息處理機制)

MessageMessage是在線程之間傳遞的消息,它可以在內部攜帶少量的信息,用於在不同線程之間交換數據。
HandlerHandler主要用於發送和處理消息的,發送消息一般是使用Handler的sendMessage()方法,而發出的消息經過處理後,最終會傳遞到Handler的handlerMessage()方法中
MessageQueue消息隊列,用於存放所有通過Handler發送的消息。每個線程只有一個MessageQueue對象
LooperLooper是每個線程的MessageQueue的管家,調用Looper的loop()方法後,就會進入到一個無限循環當中,然後每當發現MessageQueue中存在一條消息,就會將他取出,並傳遞到Handler的handlerMessage()方法中。每個線程也只會有一個Looper對象

處理過程

  1. 在主線程創建Handler對象。
  2. 重寫 handlerMessage() 方法。
  3. 當子線程需要UI操作時,就創建一個Message對象,並通過Handler將這條消息發出去。
  4. 這條消息被添加到MessageQueue中等待處理,最後分發回handlerMessage中。
  5. 由於Handler是在主線程創建的,所以此時handlerMessage()方法也在主線程中運行,於是就可以進行UI操作了。

舉例

利用Handler修改子線程UI,這裏簡單演示修改TextView的文字。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView show;

    public static final int UPDATE_TEXT = 1;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //接收,判斷,處理消息
            switch (msg.what) {
                case UPDATE_TEXT:
                    show.setText("更改UI");
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //一個Textview,修改文字來達到模擬更改界面UI的效果
        show = (TextView) findViewById(R.id.tv_show);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_show:
                //開啓線程(這裏是模擬在線程裏要修改UI的情況)
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //定義一個Message,可以發送給Handler
                        Message myMessage = new Message();
                        //用戶定義的消息代碼,以便接收者能夠識別該消息的內容。
                        myMessage.what = UPDATE_TEXT;
                        //把myMessage放到消息隊列的末尾,它將在handleMessage(Message)中接收
                        handler.sendMessage(myMessage);
                    }
                });
            default:
                break;
        }
    }
}

給message設置數據

如果你需要發送數據,那麼可以往message裏放一個Bundle類型的數據,如下

    //設置數據
    Bundle bundle = new Bundle();
    bundle.putInt("data1", 1);
    bundle.putString("data2", "數據二");
    message.setData(bundle);

在handleMessage中將數據取出

    //取出數據
    int data1 = msg.getData().getInt("data1");
    String data2 = msg.getData().getString("data2");

sendEmptyMessage()

如果你不需要設置數據,其實不用像上面例子那樣麻煩,使用sendEmptyMessage()方法可以一行解決,相當於直接發個msg.what給handler了,可以做個對比。

	//方法1用三行代碼
	Message myMessage = new Message();
	myMessage.what = UPDATE_TEXT;
	handler.sendMessage(myMessage);
	
	//方法2只用一行代碼
	handler.sendEmptyMessage(UPDATE_TEXT)

Handler+TimerTask(3個步驟)

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    Log.e(TAG, "收到信息");
            }
            super.handleMessage(msg);
        }
    };
    Timer timer=new Timer();
    TimerTask task=new TimerTask(){
        @Override
        public void run() {
            Message message = new Message();
            message.what=1;
            handler.sendMessage(message);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //延遲5秒發送消息
        timer.schedule(task,5000);
    }

Handler+Runnable(3個步驟)

    Handler handler = new Handler();
    Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            Log.e(TAG, "開始工作");
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //執行任務
        handler.post(mRunnable);
    }

簡單的循環定時器

每隔一秒執行一次work()函數

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    
    Handler handler = new Handler();
    
    Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            work();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //第一次調用work函數
        work();
    }
    
    //定義work函數
    public void work() {
        handler.postDelayed(mRunnable, 1000);
        Log.e(TAG, "收到信息");
    }
}

HandlerThread

關於HandlerThread的寫了另外一篇,感興趣的可以看下,把耗時的操作放到子線程中去,比如下載文件。而主線程通過收到子線程的各種動態,比如子線程開始下載、子線程下載完成來修改主頁面的UI,可以彈個框提示,或者修改TextView文字等等…傳送~傳送


感謝
https://www.cnblogs.com/wlming/p/5553207.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章