Android之Handler詳解

handler是什麼?

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

 

android中更新ui四種方式:

1、runonui

只能在Activity中使用

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textView);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                updateUI();

            }
        }).start();
    }

    private void updateUI() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                textView.setText("run on UI thread");
            }
        });
    }

2、view.post(runable)

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textView);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                viewUI();

            }
        }).start();
    }

    private void viewUI() {
        textView.post(new Runnable() {
            @Override
            public void run() {
                textView.setText("view update UI");
            }
        });
    }

3、handler.post()

private  Handler mhandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            
        }
    };
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textView);

        new Thread(new Runnable() {
            @Override
            public void run() {
                mhandler.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("update thread");
                    }
                });
            }
        }).start();
    }

4、handler.sendmessage

private  Handler mhandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            textView.setText(msg.arg1 + msg.arg2 + msg.obj.toString());
        }
    };
    private TextView textView;

    class Person {
        private String name;

        public Person(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textView);

        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    Thread.sleep(2000);
                    Message msg = new Message();
                    msg.arg1 = 1;
                    msg.arg2 = 2;
                    msg.obj = new Person("Gomez");
                    mhandler.sendMessage(msg);
                    //第二種發送消息方法
//                    msg = mhandler.obtainMessage();
//                    msg.sendToTarget();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

子線程創建Handler

private  Handler mhandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            System.out.println("UIThread:" + Thread.currentThread());
        }
    };
    private TextView textView;
    private MyThread myThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textView);
        myThread = new MyThread();
        myThread.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myThread.handler.sendEmptyMessage(1);
        mhandler.sendEmptyMessage(1);
    }

    class MyThread extends Thread {
        Handler handler;

        @Override
        public void run() {
            super.run();
            //初始化looper
            Looper.prepare();
            handler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    System.out.println("currentThread:" + Thread.currentThread());
                }
            };
            //循環讀取消息
            Looper.loop();
        }
    }


}

運行效果:

HandlerThread

  • HandlerThread本質上是一個線程類,它繼承了Thread;
  • HandlerThread有自己的內部Looper對象,可以進行looper循環;
  • 通過獲取HandlerThread的looper對象傳遞給Handler對象,可以在handleMessage方法中執行異步任務。
  • 創建HandlerThread後必須先調用HandlerThread.start()方法,Thread會先調用run方法,創建Looper對象。


通過HandlerThread可以避免自定義線程中很多空指針問題,如上例如果不在主線程中加入延時,那個我們拿到的子線程的handler是爲空的。

 private HandlerThread handlerThread;
    private Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handlerThread = new HandlerThread("handler thread");
        handlerThread.start();
        handler = new Handler(handlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                System.out.println("current thread" + Thread.currentThread());
            }
        };
        handler.sendEmptyMessage(1);
    }
    

在HandlerThread拿到的Looper都是安全的,在內部已經處理多線程同步;

這樣所有handleMessage都是在子線程中執行,用HandlerThread模擬一些異步任務,主線程給子線發送消息,子線程執行一些耗時操作,比如一些下載圖片,訪問服務器都可以這樣去執行。

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