用handler传递消息时候。你先sendmessage。这时候消息到looper然后你再looper当中更具msgwhat获取相应的消息。looper相当于一个消息收取中介。所以要有循环。我自己的理解。首先,Handler,Looper,MessageQueue这三者如何关联的?这里拿最简单的new 一个无参Handler为例。在创建无参的Handler时会对其中变量MessageQueue赋值,这个值就是Looper对象的MessageQueue,那么这个Looper对象又是在那创建的呢?如果是在app进程中的话,在启动该app时会调用ActivityThread,main方法进入主线程,在main函数中会有初始化Looper,并调用looperloop()轮询MessageQueue中的Message,这个Message是handler在调用sendMessage或者post时会将Message enqueue到MessageQueue中,这样Looper 就会loop 到Handler发送到MessageQueue中的Message,loop时就会dispatchMessage了,再然后就是Hanlder处理message了,在调用sendMessage时,handler必须要重写handleMessage方法。这样就完成了发送消息和处理消息。在app的进程中,thread1还是发送消息到主线程中的MessageQueue,这个MessageQueue在首次启动app时就在创建Looper时已经创建好了。那么如果不是在app进程怎么办呢?假如是在ActivityManagerService中使用Handler的话呢?ActivityManagerService可以理解为在system_server进程中的一个线程,在启动system_server时并没有像启动一个app进程那样系统已经创建好了Looper,那么咱们如果要使用Handler机制,就必须要有Handler,Looper,MessageQueue,Messag,另外,系统也已经封装好了,就是HandlerThread。HandlerThread是一个Thread,在里面已经将Looper,MessageQueue准备好了,这时候创建Handler时,将HandlerThread的Looper传给Handler就行了,这样Handler,Looper,MessageQueue就都有了,就可以利用Handler机制进行线程间通信了。
因为你是在主线程创建的handler实例,比如你是这样实例化handler
那么我们进到handler源码看一下
可以看到这里会调用重载的另外一个构造方法,我们再跟进
我们可以看到 mLooper=loopermyLooper(); 这是获取当前线程的looper实例,也就是主线程的looper。所以当发送消息的时候主线程就可以获取到消息。往下看系统还会mLooper是否为空,如果为空就会抛出异常,意思是当前线程没有looper实例,这也是我们在子线程中没有创建looper的实例的时候创建handler会报错的原因,主线程不会报错是因为程序在启动的时候在activitythread中的main方法就创建了looper实例,看系统源码
然后调用looperloop();就开始了消息循环。这就是为什么在主线程发消息住线程还能收到消息的原因。因为发送消息的实例是在主线程实例化的就有了主线程的looper。
Looperprepare()方法在当前线程里面调用,目的是创建一个新的Looper,且一个线程只能创建一个Looperpublic static void prepare() {if (sThreadLocalget() != null) {throw new RuntimeException("Only one Looper may be created per thread");}sThreadLocalset(new Looper());}public void set(T value) {Thread currentThread = ThreadcurrentThread();Values values = values(currentThread);if (values == null) {values = initializeValues(currentThread);}valuesput(this, value);}可以看出set的时候绑定了currentThread。使用Looper判断,方法为: LoopermyLooper() != LoopergetMainLooper()使用线程句柄判断,将主线程的ThreadcurrentThread()获取到主线程当前句柄,保存起来,在需要判断的时候调用ThreadcurrentThread()来与之比较,即可判断当前线程是否是主线程了
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)