Handler

Handler机制详细解析请参考参考
android中handler的一些总结以及使用(一)之handler的基本用法
android中handler的一些总结以及使用(二)之handle使用时用到的几个主要方法介绍
android中handler的一些总结以及使用(三)之HandleThread的使用

Handler简介

Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制,可以用来在多线程间进行通信,典型案例就是在另一个线程中更新UI界面。

说到handler就不得不说Looper和MessageQueue,handler主要作用是发送消息(message)和处理消息,MessageQueue的作用是存储handler发送过来的Message,Looper顾名思义,就是不断地循环消息队列(MessageQueue),取出消息,交给handler执行。handler在初始化的时候会去绑定Looper,一个线程只能一个Looper,一个Looper中也只有一个MessageQueue,三者相互协同共同完成任务,缺一不可。

handler的使用

每次你新创建一个Handle对象,它会绑定于创建它的线程(也就是UI线程)以及该线程的消息队列,Handler可以把一个Message对象或者Runnable对象压入到消息队列中,进而在UI线程中获取Message或者执行Runnable对象,Handler把压入消息队列有两类方式

handler的基本用法

(1)主线程与子线程之间的通信

public class HandlerTest extends AppCompatActivity {
 
    private static final String TAG = "HandlerTest";
    private Message mMessage;
 
    // new 一个handler实例,覆写 handleMessage()方法,用于处理消息
    private  Handler mHandle = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){                  //根据msg.what区分是消息类型
                case 0:
                    Log.d(TAG,"handleMessage of type 0");   // 根据不同消息类型,写出具体的处理方式
                case 1:
                    Log.d(TAG,"handleMessage of type 1");
            }
        }
    };
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_test);
        
        new Thread(new Runnable() {
            @Override
            public void run() {
 
                // 首先需要创建message对象,有以下三种方式
                // 1、 new Message()
                mMessage = new Message();
 
                // 2、调用Message类的静态方法 (推荐使用)
                mMessage = Message.obtain();
 
                // 3、调用handler类的方法(此方法是调用Message.obtain(Handler h)方法去创建Message对象)
                mMessage = mHandle.obtainMessage();
                
                mMessage.what = 0;     // 不同的what值,用于区分不同的消息类型 
                
                // 发送消息到MessageQueue
                mHandle.sendMessage(mMessage);
            }
        }).start();
    }
}

(2)子线程与子线程之间的通信

前面说handler初始化时需要绑定Looper,上面的例子中我们并没有绑定写Looper,为什么也可以呢?
是因为我们的应用在启动时,ActivityManager会去创建ActivityThread,用以维护Activity生命周期。ActivityThread中的main()方法应用的入口,在main()方法中,会去创建一个Looper对象,存储在线程的ThreadLocal对象中,handler在初始化时,会从ThreadLocal对象中去读取当前线程的Looper,所以才不需要我们手动去创建一个Looper。

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_test);
 
        final Thread Thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();               // 创建一个Looper对象
                mHandle = new Handler(){            
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        Log.d(TAG,"handleMessage in Child Thread");
                    }
                };
                Looper.loop();                  // 开始循环消息队列
            }
        });
 
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG,"enter send handleMessage");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                }
                mHandle.sendEmptyMessageDelayed(1,5000);  
            }
        });
 
        Thread1.start();
        thread2.start();
    }
}

thread2发送消息到thread1中的handler,实现子线程与子线程间的通信。

(3)handler发送消息的方法

1、sendMessage      立即发送信息

2、sendEmptyMessage    立即发送空消息

3、sendMessageDelayed    指定延时多少毫秒后发送信息

4、sendEmptyMessageDelayed        指定延时多少毫秒后发送空信息

5、sendMessageAtTime    指定在什么时间发送消息

6、sendEmptyMessageAtTime    指定在什么时间发送空消息

7、post    立即发送信息

8、postAtTime    指定在什么时间发送消息

9、postDelayed     指定延时多少毫秒后发送信息

以上9个方法实际上最终都是调用sendMessageAtTime方法,让我们看看两个典型的方法sendMessage和post

sendMessage方法源码:

public final boolean sendMessage(Message msg){
     return sendMessageDelayed(msg, 0); //调用sendMessageDelay方法
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);  //调用sendMessageAtTime方法
 }
    
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
 } 

post方法源码:

public final boolean post(Runnable r){
       return  sendMessageDelayed(getPostMessage(r), 0);  //最终也是调用sendMessageAtTime
    }
    
private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();   //创建一个message对象,上一节讲message获取的几种方式时,我们也有提到过
        m.callback = r;    //将此Runable对象保存在message的callback变量上
        return m;
    }

可以看出最后都是调用了sendMessageAtTime方法,最后再调用enqueueMessage

 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;  //message的target属性保存着发送此消息的handler,建立了两者的对应关系
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);    //保存消息到队列中
    }

handler发送消息后,该消息保存到消息队列中,上面我们提到过,loop方法会不断循环消息队列取出消息,然后交给目标handler(也就是message的target属性对应的handler,从这看一个队列是可以被多个handler共享的,但是一个handler只能绑定一个队列)处理。

android 中更新UI的几种方式

常见的大概有四种:runOnUiThread、handler.post、handler.sendMessage、view.post

public class FiveActivity extends Activity {  
    // 只是在布局布置一个 TextView  
    private TextView textView;  
    // 通过Handler来更新一下UI  
    Handler handler = new Handler() {  
        // 实现一下Handler里面的handleMessage方法  
        public void handleMessage(android.os.Message msg) {  
            // 第二个方法是从外边拿到数据然后返回到里面  
            textView.setText("第二种方法handlerEmptyMessags");  
        }  
    };  
  
    /** 
     * 第一方法 Handler post 
     */  
    public void handler1() {  
        handler.post(new Runnable() {  
  
            @Override  
            public void run() {  
                // 这里弄个文本消息  
                textView.setText("第一种方法Handler post");  
  
            }  
        });  
    }  
  
    /** 
     * 第二种方法 sendEmptyMessage 
     */  
    public void handler2() {  
  
        handler.sendEmptyMessage(1);  
  
    }  
  
    /** 
     * 第三种方法 runOnUiThread 
     */  
    public void handler3() {  
        runOnUiThread(new Runnable() {  
  
            @Override  
            public void run() {  
  
                textView.setText("第三个方方法runOnUiThread");  
            }  
        });  
    }  
  
    /** 
     * 第四种方法view 
     * post----它会判断当前是不是UI线程,默认情况下,会通过Handler.post发送一个action。如果是UI线程的话执行run()方法 
     */  
    public void handler4() {  
        textView.post(new Runnable() {  
  
            @Override  
            public void run() {  
  
                textView.setText("第四种方法 view post");  
  
            }  
        });  
    }  
  
    protected void onCreate(Bundle savedInstanceState) {  
        // TODO Auto-generated method stub  
        super.onCreate(savedInstanceState);  
        // 将布局,引用到这个类---因为为了方便我弄多了一个类  
        setContentView(R.layout.five);  
        // 找到ID  
        textView = (TextView) findViewById(R.id.textview);  
        // 更新UI 创建一个线程,后台处理。  
        new Thread() {  
            // 实现线程Thread 中的run方法  
            public void run() {  
  
                try {  
                    //休息两秒后再执行,因为本地网络速递较快,为了看效果。如果网络的话就去掉  
                    Thread.sleep(2000);  
  
                //  handler1();  
                //  handler2();  
                //  handler3();  
                    handler4();  
  
                } catch (InterruptedException e) {  
                    // TODO Auto-generated catch block  
                    e.printStackTrace();  
                }  
  
            };  
        }.start();  
    }  
  
}

总结:常见的四种方式更新UI都差不多,都是通过Handler来更新,只是代码上的本质而已。

在Android开发中,定时执行任务的3种实现方法

你可能感兴趣的:(Handler)