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种实现方法

更多相关文章

  1. Android源码获取方法
  2. android 消息机制(2)
  3. Android线程优先级设置方法
  4. 【Android】设置tabhost位于底部的三种方法
  5. Android Handler 异步消息处理机制的妙用 创建强大的图片加载类
  6. Mars Android视频学习笔记——01_16_SQLite使用方法
  7. 如何在Android中用好多线程
  8. Android 总结:进阶之路(资源与方法)
  9. Android 关闭所有Activity完全退出程序方法

随机推荐

  1. Android Weekly - 第 186 期
  2. Android样式基础--属性动画((Property An
  3. Android模拟器上网问题
  4. EditText属性大全(转)方便自己查阅
  5. 关于Android Studio第一次启动的Fetching
  6. 重磅消息!Android与IOS的合体!高仿IOS动态
  7. Android数据传递
  8. android仿时间轴
  9. 目前的Android恶意软件分类
  10. Fuschia 是什么样的一个操作系统