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