ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:43.82KB ,
资源ID:20476440      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/20476440.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Android中的消息机制Word下载.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Android中的消息机制Word下载.docx

1、 (klass.getModifiers() & Modifier.STATIC) = 0) Log.w(TAG, The following Handler class should be static or leaks might occur: + klass.getCanonicalName(); mLooper = Looper.myLooper(); if (mLooper = null) throw new RuntimeException(Cant create handler inside thread that has not called Looper.prepare();

2、 mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;可以看到Looper调用myLooper方法获取到Looper对象, 如果mLooper = null的话,会抛出t create handler inside thread that has not called Looper.prepare()的异常。大概的意思就是无法在没有调用Looper.prepare()的线程中创建handler。我在刚开始学习Handler的时候经常会遇到这个错误。不急,等下在分析到底为什么,现在我们只需要知道如果Looper

3、.myLooper()没有获取到Looper对象的话就会报这个错。到了这里,Handler和Looper就建立起了关联。接着往下看完最后几行代码mQueue = mLooper.mQueue;从Looper对象中取出MessageQueue对象并赋值。MessageQueue就是消息队列,那么他里面存储着很多消息吗?到了这一步,Handler通过Looper与MessageQueue也建立起了关联。我们跟踪Looper的myLooper方法进去,解决为什么会抛出Cant create handler inside thread that has not called Looper.prepar

4、e()异常。myLooper方法源码如下:public static Nullable Looper myLooper() return sThreadLocal.get();只有一行代码,从线程中取出Looper对象,那么我们有理由相信,这个ThreadLocal是通过set方法把Looper对象设置进去的。想一想ThreadLocal在哪里把Looper对象设置进去了呢。回到刚才想要解决的问题:Cant create handler inside thread that has not called Looper.prepare() 。那会不会是Looper的prepare方法呢?publ

5、ic static void prepare() prepare(true);prepare方法调用了它的一个参数的重载,那么我们就看看那个重载的方法private static void prepare(boolean quitAllowed) if (sThreadLocal.get() != null) throw new RuntimeException(Only one Looper may be created per thread sThreadLocal.set(new Looper(quitAllowed);找到了线索,ThreadLocal确实是在Looper的prepar

6、e方法里把Looper对象设置进去的,而且从第一行的判断可以知道,一个线程只有一个Looper对象。到了这里,Looper与ThreadLocal建立起了关联。可以看下Looper的构造方法private Looper(boolean quitAllowed) mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread();创建了一个MessageQueue对象。好,结合我们的分析可以知道,如果Looper没有调用prepare方法,ThreadLocal的get方法就会返回空,那么Looper.myLooper

7、()也会返回空,所以就抛出了Cant create handler inside thread that has not called Looper.prepare()的异常。那么问题又来了,我们写程序时好像没有手动调用Looper.prepare()吧,也不会抛出异常。前面提到,我们通常都是在主线程,也就是UI线程中创建handler的。而在主线程中,系统已经为我们创建了一个Looper对象,所以不会抛出异常了。而那些会抛出异常报错的情况,是在子线程中创建的handler,但是又没有调用Looper.prepare()去创建Looper对象。继续前进。那就来看看,主线程在什么时候创建了Loo

8、per对象吧。在ActivityThread的main方法,这个方法是应用程序的入口。main方法的源码如下:public static void main(String args) /代码省略 Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler = null) sMainThreadHandler = thread.getHandler(); if (false) Looper.myLooper().setM

9、essageLogging(new LogPrinter(Log.DEBUG, ActivityThread); / End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop();Main thread loop unexpectedly exited找到了Looper.prepareMainLooper(),这和Looper.prepare()太像了吧,跟进去看看public static void prepareMainLooper() prepare(fal

10、se); synchronized (Looper.class) if (sMainLooper ! throw new IllegalStateException(The main Looper has already been prepared. sMainLooper = myLooper();又兜了回来,还是调用了prepare方法的。所以主线程是已经创建了一个Looper对象的。Handler的创建过程分析完毕,现在总算搞明白了。那先总结一下,Handler的创建是依赖于Looper的。而主线程是默认创建了一个Looper对象的。每一个Looper会关联一个线程(ThreadLoca

11、l中封装了Looper)。每一个Looper中又会封装一个消息队列。这样一来,handler,Looper,MessageQueue,Thread四个角色就关联了起来,你中有我,我中有你。handler在主线程中创建,是因为要和主线程的消息队列关联起来,那样handler的handleMessage方法才会在主线程中执行,那么这样在更新UI就是线程安全的了。接着继续吧,还很多问题没有解决 相信你更想了解Handler是怎么发送消息的。通常我们是创建一个Message对象,并将一些从服务端拉取的数据,标记,参数等赋值到Message的一些字段what,arg1,obj等,handler调用sen

12、dMessage方法发送,就能将这个数据发送到主线程,然后在handlerMessage方法处理更新UI即可。那我们就从handler的sendMessage方法开始寻找信息public final boolean sendMessage(Message msg) return sendMessageDelayed(msg, 0);sendMessage会调用sendMessageDelayed方法并将message对象传进去,第二个参数是延时时间,使用sendMessage方法时默认为0的。那么来到sendMessageDelayed方法public final boolean sendMe

13、ssageDelayed(Message msg, long delayMillis) if (delayMillis 0) delayMillis = 0; return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);兜兜转转,最终会调用sendMessageAtTime方法,并将message对象传进。继续跟进sendMessageAtTime方法,public boolean sendMessageAtTime(Message msg, long uptimeMillis) MessageQueue qu

14、eue = 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);上面分析了,在创建Looper对象的时候,会创建一个MessageQueue,所以只要Looper是正常创建的话,消息队列是不为空的。那么到最后一行的enque

15、ueMessage方法,源码如下:private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) msg.target = this; if (mAsynchronous) msg.setAsynchronous(true); return queue.enqueueMessage(msg, uptimeMillis);可以看到最后一行调用了MessageQueue的enqueueMessage方法。注意: 上面贴出的enqueueMessage是Handler的方法,不是MessageQue

16、ue的,只是做了一层包装而已,真正的入队消息队列的操作当然是在MessageQueue中。而且从第一行的msg.target = this中可以知道,msg的target字段,其实就是handler。MessageQueue的enqueueMessage方法源码如下:boolean enqueueMessage(Message msg, long when) if (rget = null) throw new IllegalArgumentException(Message must have a target. if (msg.isInUse() throw new IllegalStat

17、eException(msg + This message is already in use. synchronized (this) if (mQuitting) IllegalStateException e = new IllegalStateException( msg.target + sending message to a Handler on a dead thread Log.w(TAG, e.getMessage(), e); msg.recycle(); msg.markInUse(); msg.when = when; Message p = mMessages; b

18、oolean needWake; if (p = null | when = 0 | when p.when) / New head, wake up the event queue if blocked. msg.next = p; mMessages = msg; needWake = mBlocked; else / Inserted within the middle of the queue. Usually we dont have to wake / up the event queue unless there is a barrier at the head of the q

19、ueue / and the message is the earliest asynchronous message in the queue. needWake = mBlocked & p.target = null & msg.isAsynchronous(); Message prev; for (;) prev = p; p = p.next; if (p = null | when Dispatching to + msg.target + msg.callback + : + msg.what); msg.target.dispatchMessage(msg); Finishe

20、d to + msg.callback); / Make sure that during the course of dispatching the / identity of the thread wasnt corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) Log.wtf(TAG, Thread identity changed from 0x + Long.toHexString(ident) + to 0x + Long.toHexString(newIdent

21、) + while dispatching to + msg.target.getClass().getName() + + msg.callback + what= msg.recycleUnchecked();抓重点看就好。首先是调用myLooper方法获取到Looper对象,这里是没问题的,那就继续MessageQueue queue = me.mQueue然后从Looper对象中取出关联的消息队列, 接着进入了一个死循环,调用messagequeue的next方法取出message对象。这个next方法我没看懂,所以不贴源码出来分析了,反正next方法的作用就是取出message对象的

22、。有兴趣的同学自己去研究研究吧。到这里可以总结一下:通过Looper.prepare()来创建Looper(消息循环)对象,然后通过Looper.loop()来执行消息循环,Looper.prepare()和Looper.loop()通常是成对出现的。好,回来继续 经过一系列的判断后会来到这里,很重点msg.target.dispatchMessage(msg);上面已经分析,msg.target就是handler,那么这行代码的意义就是调用handler的dispatchMessgage的方法去分发消息, 那么看到dispatchMessage的方法源码,相信谜底就要揭开了public void dispatchMessage(Message msg) if (msg.callback ! handleCallback(msg); if (mCallback ! if (mCallback.handleMessage(msg) handleMessage(msg);从上述的代码跟踪中,都没有发现给message的callback字段赋值,那么我们就先不搭理,默认callback为空,那么就一定会来到handleMessage方法。message对象传递到了handleMessage方法。/* * Su

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1