Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Handler(消息機制)的常用場景總結

Handler(消息機制)的常用場景總結

編輯:關於Android編程

1、安卓為什麼只能通過消息機制更新UI呢?

最根本的目的就是解決多線程並發問題。(多個線程同時執行一個任務)

假如在一個Activity中,有多個線程去更新UI,並且都沒有加鎖機制,那就會造成更新UI錯亂。如果對更新UI的操作都進行加鎖處理,就會造成性能下降。使用消息機制,根本不用關系多線程的問題,因為更新UI的操作,都是在主線程的消息隊列當中去輪詢處理的。

2、Handler是什麼?

Handler是android提供的一套更新UI的機制,也是消息處理機制,我們可以用它發送消息,也可以通過它處理消息。

更新UI,傳遞消息,處理消息。

3、默認情況下Handler會與其被定義時所在線程的Looper綁定,比如,Handler在主線程中定義,那麼它是與主線程的Looper綁定。

注意Handler的構造函數,New Handler()什麼參數都不需要

/**
 * Created on 2016/9/23.
 * Author:crs
 * Description:測試消息機制:主要用於線程間通訊,注意Handler類的構造函數
 * 1)一個完整的消息要包括消息標識和消息內容.(消息對象裡面包含消息消息標識和消息內容;如果是空消息,只有消息標識沒有消息體)
 *
 * 2)只有在原生線程(主線程)才能更新UI,在子線程更新UI會報錯。
 *
 * 3)使用消息機制更新UI的模板性代碼:創建Handler實例,在子線程中調用post方法,就兩步操作。
 * handler.post(r): r是要執行的任務代碼,意思就是說r的代碼實際是在UI線程執行的,可以寫更新UI的代碼。
 *
 * 4)使用消息機制更新UI的模板性代碼:創建Handler實例,重寫handleMessage()方法,創建消息對象並進行信息傳遞即可。
 * obtainMessage() Message類 arg1 arg2 sendMessage(message實例) sendToTarget(); sendEmptyMessage()
 *
 * 5)使用消息機制實現圖片輪播:創建Handler實例,創建Runnable接口實例,調用postDelayed(runnable實例,毫秒值);
 * removeCallbacks(Runnable),就這幾步常規的操作
 *
 * 6)創建Handler的時候,指定callBack;可以通過CallBack截獲Handler傳遞的消息.
 */

案例一:安卓中更新UI的四種方式

package com.crs.demo.ui.handler;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;

/**
 * Created on 2016/10/9.
 * Author:crs
 * Description:安卓中四種更新UI的方式
 * 1)handler.post()
 * 2)handler.sendMessage()
 * 3)runOnUIThread()
 * 4)View.post
 */
public class TestUpdateUIActivity extends BaseActivity {

    private static final int SUCCESS_GET_DATA = 1;
    private Handler mHandler = new Handler();
    private Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case SUCCESS_GET_DATA: {
                    tv_activity_test_update_ui.setText("使用handler.sendMessage()更新");
                }
                break;
            }
        }
    };
    private TextView tv_activity_test_update_ui;

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

        initViews();
    }

    private void initViews() {
        tv_activity_test_update_ui = findView(R.id.tv_activity_test_update_ui);
        Button btn_test_handler1 = findView(R.id.btn_test_handler1);
        Button btn_test_handler2 = findView(R.id.btn_test_handler2);
        Button btn_test_handler3 = findView(R.id.btn_test_handler3);
        Button btn_test_handler4 = findView(R.id.btn_test_handler4);

        //第一種方式:在子線程中調用runOnUIThread()更細UI
        btn_test_handler1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                tv_activity_test_update_ui.setText("調用runOnUIThread方法更新");
                            }
                        });
                    }
                }).start();

            }
        });

        //第二種方式:使用View的post()更新UI
        btn_test_handler2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_activity_test_update_ui.post(new Runnable() {
                    @Override
                    public void run() {
                        tv_activity_test_update_ui.setText("使用View的post()更新UI");
                    }
                });

            }
        });

        //第三種方式:使用Handler的post()更新UI
        btn_test_handler3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                tv_activity_test_update_ui.setText("Handler的post()更新UI");
                            }
                        });
                    }
                }).start();
            }
        });

        //第四種方式:使用Handler的sendMessage()更新UI
        btn_test_handler4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //Message message = new Message();
                        //Message message = myHandler.obtainMessage();
                        myHandler.sendEmptyMessage(SUCCESS_GET_DATA);
                    }
                }).start();
            }
        });
    }
}
案例二:攔截Handler傳遞的消息

 

 

package com.crs.demo.ui.handler;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
import com.crs.demo.utils.ToastUtils;

/**
 * Created on 2016/10/8.
 * Author:crs
 * Description:測試創建Handler指定CallBack
 */
public class TestCallBackActivity extends BaseActivity {

    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            //可以通過CallBack截獲Handler傳遞的消息,返回值表示是否截獲消息,false表示不截獲。
            ToastUtils.showShort(TestCallBackActivity.this, "1");
            //如果設置為true,就表示截獲消息,後面的handleMessage()就不在繼續執行了,即2不會被打印了。
            return false;
        }
    }) {
        @Override
        public void handleMessage(Message msg) {
            ToastUtils.showShort(TestCallBackActivity.this, "2");
        }
    };

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

        initViews();
    }

    private void initViews() {
        Button btn_activity_test_call_back = findView(R.id.btn_activity_test_call_back);
        btn_activity_test_call_back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mHandler.sendEmptyMessage(1);
            }
        });
    }
}
案例三:使用Handler實現圖片輪播效果

 

 

package com.crs.demo.ui.handler;

import android.os.Bundle;
import android.os.Handler;
import android.widget.ImageView;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;

/**
 * Created on 2016/10/8.
 * Author:crs
 * Description:使用消息機制實現圖片輪播效果
 * 關鍵是練習消息機制的使用
 */
public class TestPostDelayedActivity extends BaseActivity {

    int[] image = {R.drawable.iv_1, R.drawable.iv_2, R.drawable.iv_3};
    int index;
    private ImageView iv_test_post_delayed;

    //1)創建Handler實例
    private Handler mHandler = new Handler();
    //2)創建Runnable實例
    private MyRunnable myRunnable = new MyRunnable();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_post_delayed);
        iv_test_post_delayed = findView(R.id.iv_test_post_delayed);

        //3)調用此方法實現定時器效果
        mHandler.postDelayed(myRunnable, 1000);
    }

    //實現接口
    class MyRunnable implements Runnable {
        @Override
        public void run() {
            index++;
            //余數只有三種類型0、1、2
            index = index % 3;
            //每隔多少秒要做的事(業務邏輯)
            iv_test_post_delayed.setImageResource(image[index]);
            mHandler.postDelayed(this, 1000);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        //清除此定時器效果
        mHandler.removeCallbacks(myRunnable);
    }
}
案例四:自定義與線程相關的handler

 

 

package com.crs.demo.ui.handler;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
import com.crs.demo.utils.LogUtils;

/**
 * Created on 2016/10/9.
 * Author:crs
 * Description:自定義與線程相關的Handler
 */
public class TestCustomHandlerActivity extends BaseActivity {

    private static final String TAG = "TestCustomHandler";
    private MyThread myThread;
    //創建主線程Handler
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            LogUtils.i(TAG, Thread.currentThread() + "主線程");
        }
    };


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



        myThread = new MyThread();
        myThread.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //主線程中的Handler
        mHandler.sendEmptyMessage(1);

        //子線程中的Handler
        myThread.myHandler.sendEmptyMessage(2);
    }


    class MyThread extends Thread {
        private Handler myHandler;

        @Override
        public void run() {
            super.run();
            Looper.prepare();
            myHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    LogUtils.i(TAG, Thread.currentThread() +"子線程");
                }
            };
            Looper.loop();
        }
    }
}

 

 

Handler的原理是什麼?

1)Handler封裝了消息的發送,主要包括消息發送給誰。

2)Looper:內部包含一個消息隊列,也就是MessageQueue,所有Handler發送的消息都會走向這個消息隊列。

Looper類中有一個loop()方法,它不斷的從MessageQueue中取消息,如果有消息就處理消息,如果沒有消息就阻塞。

3)MessageQueue就是一個消息隊列,可以添加消息、移除消息。

4)Handler內部會和Looper進行關聯,在Handler內部可以找到Looper。使用Handler發送消息,其實就是向MessageQueue隊列中發送消息。

總結:handler負責發送消息,Looper負責接收Handler發送的消息,並直接發消息傳回給handler自己、MessageQueue就是一個存儲消息的容器、looper是循環器。

 

 

消息標識與消息內容(int類型和對象類型)

如何獲取一個Message對象?

Handler的兩種作用:發送消息、傳遞消息.

Message與Handler之間的關系 sendToTarget()

Handler移除一個事件,停止事件的執行removeCallBack(runnable實例)

發送一個空消息的目的是什麼原理是什麼

截獲Handler發送的消息 new CallBack()

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved