什么是Handler


定義

Handler是用來結合線程的消息隊列來發送、處理"Message對象"和"Runnable對象"的工具。

每一個Handler實例之后會關聯一個線程和該線程的消息隊列。也就是說,當你創建一個Handler的時候,從此開始,他就會自動關聯到所在的線程/消息隊列,然后它就會陸續把Message/Runnable分發到消息隊列,並在他們出隊的時候處理掉。因為android只允許在主線程中更新UI,Handler的目的就是作為線程通信的橋梁,進而再通過主線程更新UI。使用Handler這種異步回調機制,使我們可以再完成一個很長的任務后再做出相應的通知。

Handler和Message、MessageQueue、Looper之間的關系

Message

Handler接收與處理的消息對象

MessageQueue

消息隊列,以先進先出隊列形式管理所有的Message,且在初始化Looper對象時會創建一個與之關聯的MessageQueue。每個線程最多只有一個MessageQueue。MessageQueue通常都是由Looper來管理,而主線程創建時,會創建一個默認的Looper對象,而Looper對象的創建,將自動創建一個MessageQueue。其他非主線程,不會自動創建Looper。

Looper

每個線程只能夠一個Looper,管理MessageQueue,不斷從中去除Message分發給對應的Handler處理。

通俗一點講:當我們的子線程想修改Activity中的UI組件時,我們可以新建一個Handler對象,通過這個對象向主線程發送消息;而我們發送的消息會先到主線程的MessageQueue中進行等待,由Looper按先入先出順序取出,再根據Message對象的what屬性分發給對應的Handler進行處理。

Handler的主要用途

1.推送未來某個時間點將要執行的Message或者Runnable到消息隊列

 

通過Handler+Message的方式更新UI

 

public class MainActivity extends AppCompatActivity {

    private TextView text;

    private static final int UPDATE_TEXT = 1;  //整型常量用於表示更新TextView這個動作

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.id.activity_main);
        text = (TextView) findViewById(R.id.text); 
        Button chaneText = (Button) findViewById(R.id.change_text);
        change_text.setOnClickListener(this);
    }

    //新增Handler對象,並重寫父類的handlerMessage()方法,在這里對具體的Message進行處理
    private Handler handler = new Handler(){  
        public void handleMessage(Message msg){  //收到消息,在HandleMessage()方法中對消息進行處理
            switch (msg.what){
                case UPDATE_TEXT:
                // 在這里進行UI操作,處於主線程中
                    text.setText("Nice to meet you");
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    public void onClick(View v){
        switch(v.getId()){
            case R.id.change_text:
                new Thread(new Runnable(){
                    @Override
                    public void run(){
                        Message message = new Message();
                        message.what = UPDATE_TEXT;    //將waht字段的值指定為UPDATE_TEXT
                        handler.sendMessage(message);    //調用Handler的sendMessage()方法發送消息
                    }
                }).start();
                break;
            default:
                break;
        }
    }
}

 

 

 

2.在子線程把需要在另一個線程執行的操作加入到消息隊列中去

通過Handler + Message來實現子線程加載圖片,在UI線程顯示圖片

public class ThreadActivity extends AppCompatActivity implements View.OnClickListener {
    private ActivityThreadBinding mBinding = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_thread);
        // 設置點擊事件
        mBinding.clickBtn.setOnClickListener(this);
        mBinding.resetBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            // 響應load按鈕
            case R.id.clickBtn:
                // 開啟一個線程
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // 在Runnable中進行網絡讀取操作,返回bitmap
                        final Bitmap bitmap = loadPicFromInternet();
                        // 在子線程中實例化Handler同樣是可以的,只要在構造函數的參數中傳入主線程的Looper即可
                        Handler handler = new Handler(Looper.getMainLooper());
                        // 通過Handler的post Runnable到UI線程的MessageQueue中去即可
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                // 在MessageQueue出隊該Runnable時進行的操作
                                mBinding.photo.setImageBitmap(bitmap);
                            }
                        });
                    }
                }).start();
                break;
            case R.id.resetBtn:
                mBinding.photo.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.default_pic));
                break;
        }
    }

    /***
     * HttpUrlConnection加載圖片,不多說
     * @return
     */
    public Bitmap loadPicFromInternet() {
        Bitmap bitmap = null;
        int respondCode = 0;
        InputStream is = null;
        try {
            URL url = new URL("https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1421494343,3838991329&fm=23&gp=0.jpg");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(10 * 1000);
            connection.setReadTimeout(5 * 1000);
            connection.connect();
            respondCode = connection.getResponseCode();
            if (respondCode == 200) {
                is = connection.getInputStream();
                bitmap = BitmapFactory.decodeStream(is);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(), "訪問失敗", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bitmap;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM