看了这么多的文章,终于看懂了。
参考文献:
1、从定义上理解Handler
首先有一下参考文献【1】中的一句英文句子来说明下:
A Handler allows you to send and process
Message
and Runnable objects associated with a thread's MessageQueue
. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
——以上简单来说,就是每个Handler的实例创建的时候都会关联一个
线程和线程的的
消息队列,并且Handler运行发送和执行Message和Runnable对象。(如果后面半句没理解,没事,请继续往下看)
Scheduling messages is accomplished with the
post(Runnable)
,
postAtTime(Runnable, long)
,
postDelayed(Runnable, long)
,
sendEmptyMessage(int)
,
sendMessage(Message)
,
sendMessageAtTime(Message, long)
, and
sendMessageDelayed(Message, long)
methods.
——这段仅仅是说明了,有这多方法可以使用,归纳来说就是一个post()和一个sendMessage()方法,这里主要是讲如何向消息队列发送消息。(这段不管)
The
post
versions allow you to enqueue
Runnable
objects to be called by the message queue
when they are received
; the
sendMessage
versions allow you to enqueue a
Message
object containing a bundle of data that will be processed by the Handler's
handleMessage(Message)
method (requiring that you implement a subclass of Handler).
——【精华】这段主要讲,接受出来。post的Runnable对象将会插入消息队列,之后将会被关联的线程调用执行;使用
sendMessage
将包含
bundle of data
的message插入到消息队列中,通过
handleMessage(Message)
这个函数来获取其值。
说白了,通过Handler可以在两个线程中实现通信。
为什么要使用
Handler
,举个简单的例子,Android的UI主线程只有一个,如果在UI线程中执行网络操作等十分费时操作,将会影响APP的流程度,并且Android系统存在若APP在5秒内不能响应用户的操作,将认为运行不顺,弹出阻止程序运行的窗口。
2、示例程序
2.1 post 示例程序
public class NasaDaliyImage extends Activity {
public IotdHandler handler;
private ProgressDialog dialog;
private Handler handlerRun ;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nasa_daliy_image);
handlerRun =new Handler();//将Handler关联至UI线程
refreshFromFeed();
}
private void refreshFromFeed() {
// doSomeThing 可执行UI操作
Thread th = new Thread() { //新建线程
public void run() {
//执行耗时的网络操作等
handlerRun.post( // post Runnable对象
new Runnable () { //实现Runnable接口
public void run() { //重写Runnable的run()方法
//执行UI操作
}
}
);
}
};
th.start(); //线程启动
}
2.2 sendMessage示例程序
根据参考文献【2】得到如下代码
2.2.1
创建Handler实现类,在主UI所在类中的内部类
class MyHandler extends Handler { public MyHandler() { } public MyHandler(Looper L) { super(L); //Use the provided Looper instead of the default one. } // 重写handleMessage方法,接受数据并更新UI @Override public void handleMessage(Message msg) { super.handleMessage(msg); //此处根据msg内容进行UI操作 } } // 在UI线程中执行 MyHandler handler = new MyHandler();不带参数将默认管理UI线程。
2.2.2
子线程的实现
class MyThread implements Runnable { public void run() { //执行费时的操作 Message msg = new Message(); Bundle b = new Bundle(); b.putString("cmd", "update"); msg.setData(b); MainActivity.this.myHandler.sendMessage(msg);//通知Handler更新UI MainActivity为其主线程 } }
3、 Android Thread Looper Handler 关系
参考文献【3】具体如下:
Thread,A Thread is a concurrent unit of execution
线程是一个并发的执行单位。
Looper,Class used to run a message loop for a thread.维护线程的消息循环类。
Handler,A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue。向消息队列发送消息(Runnable object),或者执行消息队列的消息(Runnable object).
其中三者之间的关系见下图(图片来自【4】):
从上图中,可以了解到在一个Main Thread中包含一个Looper,并且Looper包含一个消息队列,在将一个Handler MyHandler关联至Main Thread
在Worker Thread中sendMessage 或者 post至消息队列中,之后由管理消息队列的Looper将其取出,如果是Runnable则进行执行,如果是Message则
调用相应的Handler的
handleMessage
来获取。
下面介绍下Looper
looper启动例程序如下:
public class LooperThread extends Thread { private Handler handler1; private Handler handler2; @Override public void run() { // 将当前线程初始化为Looper线程 Looper.prepare(); // 实例化两个handler handler1 = new Handler(); handler2 = new Handler(); // 开始循环处理消息队列 Looper.loop(); } }
其中app启动Activity的源代码也有相应的代码:
ActivityThread.java public static final void main(String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); // 这里闭合消息循环 Looper.loop(); }
其中Looper.loop();是looper不断的读取队列中的消息
之后在\sdk\sources\android-16\android\os\的Looper.java中的 public static void loop()中可以大致看到如下代码,参考【4】
获取消息,并通过调用
dispatchMessage
(msg)函数来处理消息
再次查看位于 \sdk\sources\android-16\android\os\Handler.java中的 dispatchMessage函数,分别执行Runnable或者调用 handleMessage进行处理。public static final void loop() { Looper me = myLooper(); //得到当前线程Looper MessageQueue queue = me.mQueue; //得到当前looper的MQ // 这两行没看懂= = 不过不影响理解 Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); // 开始循环 while (true) { Message msg = queue.next(); // 取出message if (msg != null) { if (msg.target == null) { // message没有target为结束信号,退出循环 return; } // 日志。。。 if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); // 非常重要!将真正的处理工作交给message的target,即后面要讲的handler msg.target.dispatchMessage(msg); // 还是日志。。。 if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); // 下面没看懂,同样不影响理解 final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf("Looper", "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } // 回收message资源 msg.recycle(); } } }
// 处理消息,该方法由looper调用 public void dispatchMessage(Message msg) { if (msg.callback != null) { // 如果message设置了callback,即runnable消息,处理callback! handleCallback(msg); } else { // 如果handler本身设置了callback,则执行callback if (mCallback != null) { /* 这种方法允许让activity等来实现Handler.Callback接口,避免了自己编写handler重写handleMessage方法。 if (mCallback.handleMessage(msg)) { return; } } // 如果message没有callback,则调用handler的钩子方法handleMessage handleMessage(msg); } } // 处理runnable消息 private final void handleCallback(Message message) { message.callback.run(); //直接调用run方法! } // 由子类实现的钩子方法 public void handleMessage(Message msg) { }