Handler

[toc]

Handler 是一个消息分发对象。handler是Android给我们提供用来更新UI的一套机制,也是一套消息处理机制,我们可以发消息,也可以通过它处理消息

由于非UI线程无法修改界面(主要的原因是防止数据不一致)

那么,如果直接创建一个线程,进行UI更新操作,程序会崩掉:

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

                Toast.makeText(MainActivity.this,"获取到消息",Toast.LENGTH_SHORT).show();

            }
        }).start();

发送消息

// 成员变量
private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            Toast.makeText(MainActivity.this,"获取到消息"+msg.what,Toast.LENGTH_SHORT).show();
            return true;
        }
    });

// 创建一个发送消息给Handler
new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                Toast.makeText(MainActivity.this,"获取到消息",Toast.LENGTH_SHORT).show();
                Message message = new Message();
                message.what=0x123;
                handler.sendMessage(message);
            }
        }).start();

直接让Handler执行一段代码

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

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"获取到消息",Toast.LENGTH_SHORT).show();
                    }
                });

            }
        }).start();

Callback

这个类是Handler的一个内部类,作用主要是回调,在上面的例子我们已经认识到它的作用了

UI线程与子线程通信

  • Looper:类似一个消息泵。它本身是一个死循环,不断地从MessageQueue中提取Message或者Runnable
  • MessageQueue:一个消息队列,可以看作是一个容器,用来存放消息

而Handler可以看做是一个Looper的暴露接口,向外部暴露一些事件,并暴露sendMessage()和post()函数

除了UI线程/主线程以外,普通的线程(先不提HandlerThread)是不自带Looper的

更新UI的四种方式

  • 使用Handler消息传递
  • Handler的post
  • AsyncTask
  • Activity.runOnUiThread
  • View.post 后两种本质上也是使用了Handler

非UI线程更新UI

在oncreate方法中开启子线程更新ui,在thread没有休眠的情况下,因为ViewRootImp在activity的onresume方法中创建,在ViewRootImp方法中判断当前线程是否为主线程,oncreate在onresume之前执行,所以这种情况下,可以进行更新ui操作

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

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

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"获取到消息",Toast.LENGTH_SHORT).show();
                    }
                });

            }
        }).start();

    }

以上代码可以正确运行

results matching " "

No results matching " "

results matching " "

No results matching " "