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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

Android基础之异步消息处理机制.docx

1、Android基础之异步消息处理机制Android基础之异步消息处理机制今天讲述一下Android的异步消息处理机制,说到异步,我们肯定会想到继承Thread,实现Runnable来处理耗时操作,然后再发消息去处理对应的业务逻辑。相信大家对下面的代码非常熟悉。public class MainActivity extends Activity private static final int MESSAGE = 1; private static Handler mHandler = new Handler() Override public void handleMessage(Messag

2、e msg) / TODO Auto-generated method stub super.handleMessage(msg); Log.i(Log,text); ; Override protected void onCreate(Bundle savedInstanceState) / TODO Auto-generated method stub super.onCreate(savedInstanceState); CustomThread thread = new CustomThread(); thread.start(); CustomRunnable runnable =

3、new CustomRunnable(); runnable.run(); private class CustomThread extends Thread Override public void run() / TODO Auto-generated method stub super.run(); mHandler.sendEmptyMessage(MESSAGE); ; private class CustomRunnable implements Runnable Override public void run() / TODO Auto-generated method stu

4、b mHandler.sendEmptyMessage(MESSAGE); 然而这次的主要内容就是消息处理的原理。 我们首先了解一下以下各元素:Message:消息MessageQuene:消息队列,可以添加消息,处理消息。Looper:消息循环,用于循环取出消息进行处理。Handler:发送消息;消息循环从消息队列中取出消息后要对消息进行处理。我们来看Handler的无参构造方法: public Handler() this(null, false); public Handler(Callback callback, boolean async) if (FIND_POTENTIAL_LE

5、AKS) final Class klass = getClass(); if (klass.isAnonymousClass() | klass.isMemberClass() | klass.isLocalClass() & (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 (

6、mLooper = null) throw new RuntimeException( Cant create handler inside thread that has not called Looper.prepare(); mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; 可以看到,在第10行调用了Looper.myLooper()方法来获取一个Looper对象,如果对象为空,会抛出一个RuntimeException。在获取到当前线程保存的Looper实例后,再获取了这个Looper实例中保存的

7、MessageQueue(消息队列),这样handler、Looper、MessageQueue三者之间就关联上了。我们这接着看Looper.myLooper()是怎么处理的。 public static Nullable Looper myLooper() return sThreadLocal.get(); 在当前线程会get他的消息循环器Looper,在有get(),就肯定有set(),我们可以想到在Looper.prepare()里面set()。那么我们继续往下看源码: public static void prepare() prepare(true); private static

8、 void prepare(boolean quitAllowed) if (sThreadLocal.get() != null) throw new RuntimeException(Only one Looper may be created per thread); sThreadLocal.set(new Looper(quitAllowed); 这里判断是否已经存在Looper,如果不存在则new一个新的Looper,所以说要先有一个消息循环器Looper,才能创建Handler对象。同时也可以看出每一个线程sThreadLocal只会有一个Looper对象。我们接着看Looper

9、初始化做了些什么? private Looper(boolean quitAllowed) mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); MessageQueue(boolean quitAllowed) mQuitAllowed = quitAllowed; mPtr = nativeInit(); 在Looper初始化时,新建了一个MessageQueue的对象,赋予mQueue中,MessageQueue的构造方法访问是包可见,所以我们是无法直接使用的。然后还有nativeInit(),

10、nativeInit() 方法创建 NativeMessageQueue 对象,并将这个对象的指针复制给 Android MessageQueue 的 mPtr。关于C+中的nativeXXX方法不做过多分析,需要深究的同学自行查阅资料,我们只要明白mPtr为native层的MessageQueue的指针即可。此时,回到上面,有同学会说,你这个Looper.prepare(),没有在Handler的构造方法出现啊,是怎么回事。那么我们可以去看一下ActivityThread的main()方法,系统已经帮我们自动调用Looper.prepare()方法了。代码如下: public static

11、void main(String args) SamplingProfilerIntegration.start(); CloseGuard.setEnabled(false); Environment.initForCurrentUser(); EventLogger.setReporter(new EventLoggingReporter(); Process.setArgV0(); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMai

12、nThreadHandler = null) sMainThreadHandler = thread.getHandler(); AsyncTask.init(); if (false) Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, ActivityThread); Looper.loop(); throw new RuntimeException(Main thread loop unexpectedly exited); 在第七行调用了Looper.prepareMainLooper()方法。而这个方法又会再去调

13、用Looper.prepare()方法,在最后又会调用Looper.loop()方法,这就是我们平时创建Handler时不写这两个方法的原因。接着我们看prepareMainLooper()代码如下所示: public static void prepareMainLooper() prepare(false); synchronized (Looper.class) if (sMainLooper != null) throw new IllegalStateException(The main Looper has already been prepared.); sMainLooper

14、= myLooper(); 这里Main线程(UI线程)初始化消息循环时会调用prepareMainLooper,传进去的是false,消息循环不可以退出,上面说在默认构造方法时可以。接着是调用myLooper(),创建一个消息循环器Looper,因此我们应用程序的主线程中会始终存在一个Looper对象,从而不需要再手动去调用Looper.prepare()方法了。这样我们大致理顺了Handler的创建过程。那么在创建Handler之后,我们是开线程,线程处理完之后用handler发送消息Message,在文章一开头就演示了一个handler.sendEmptyMessage(arg)。然后我

15、们去翻一下Handler类里面提供了很多发送消息的方法,但是它们最终都是调用sendMessageAtTime(Message msg, long uptimeMillis),这里面发送消息的方法我就不贴了,大家可以去翻翻SDK源码验证下,接着我们直接看sendMessageAtTime()方法源码: public boolean sendMessageAtTime(Message msg, long uptimeMillis) MessageQueue queue = mQueue; if (queue = null) RuntimeException e = new RuntimeExce

16、ption( this + sendMessageAtTime() called with no mQueue); Log.w(Looper, e.getMessage(), e); return false; return enqueueMessage(queue, msg, uptimeMillis); private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) msg.target = this; if (mAsynchronous) msg.setAsynchronous(true

17、); return queue.enqueueMessage(msg, uptimeMillis); mQueue是一个全局变量,在创建Handler的时候,获取到消息循环器Looper之后,会mQueue = mLooper.mQueue。这里面msg参数就是我们发送的Message对象,而uptimeMillis参数则表示发送消息的时间。我们看到queue.enqueueMessage()方法,这里是MessageQueue类里面的方法,MessageQueue的作用我们上面也简述过,它是一个消息队列,用于将所有收到的消息以队列的形式进行排列,并提供入队和出队的方法。源码如下: final

18、 boolean enqueueMessage(Message msg, long when) if (msg.when != 0) throw new AndroidRuntimeException(msg + This message is already in use.); if (msg.target = null & !mQuitAllowed) throw new RuntimeException(Main thread not allowed to quit); synchronized (this) if (mQuiting) RuntimeException e = new

19、RuntimeException(msg.target + sending message to a Handler on a dead thread); Log.w(MessageQueue, e.getMessage(), e); return lse; else if (msg.target = null) mQuiting = true; msg.when = when; Message p = mMessages; if (p = null | when = 0 | when p.when) msg.next = p; mMessages = msg; this.notify();

20、else Message prev = null; while (p != null & p.when Dispatching to + msg.target + + msg.callback + : + msg.what); msg.target.dispatchMessage(msg); if (logging != null) logging.println( Finished to + msg.target + + msg.callback); / Make sure that during the course of dispatching the / identity of the

21、 ead 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) + while dispatching to + msg.target.getClass().getName() + + msg.callback + what= + msg.what);

22、 msg.recycleUnchecked(); 从一开始myLooper()可以看出如果me为null则抛出异常,也就是说looper方法必须在prepare方法之后运行。接着在for (;)看到,进入的是一个死循环,然后不断地调用的MessageQueue的next()方法,这个next()方法就是消息队列的出队方法。它的简单逻辑就是如果当前MessageQueue中存在mMessages(即待处理消息),就将这个消息出队,然后让下一条消息成为mMessages,否则就进入一个阻塞状态,一直等到有新的消息入队。每当有一个消息出队,就将它传递到msg.target的dispatchMessa

23、ge()方法中,msg的target就是handler对象。【在上面Handler的发送消息enqueueMessage()方法中就首先为meg.target赋值为this】,而Message被处理后会被recycle。当queue.next返回null时会退出消息循环。接下来当然就要看一看Handler中dispatchMessage()方法的源码了,如下所示: public void dispatchMessage(Message msg) if (msg.callback != null) handleCallback(msg); else if (mCallback != null)

24、if (mCallback.handleMessage(msg) return; handleMessage(msg); 在第5行进行判断,如果mCallback不为空,则调用mCallback的handleMessage()方法,否则直接调用Handler的handleMessage()方法,并将消息对象作为参数传递过去。这样就可以理解到在handleMessage()方法中可以获取到之前发送的消息了。另外在Looper类开头注释的地方在着官方给的标准异步消息处理线程的写法: class LooperThread extends Thread public Handler mHandler;

25、 public void run() Looper.prepare(); mHandler = new Handler() public void handleMessage(Message msg) / process incoming messages here ; Looper.loop(); 上述基本把这个流程解释完毕了,我们简单总结一下: 借郭哥图一用:1. 首先Looper.prepare()在当前主线程会创建一个Looper的实例对象,然后该实例中会创建一个MessaheQueue对象,由于Looper.prepare()在线程中有判断是否已存在消息循环器(Looper),存在则

26、不创建,因此一个Looper对应着一个消息队列(MessageQueue)。 2. 在Looper.loop()方法中会让当前的线程进入到一个死循环中,不断地从MessageQueue中读取消息,然后回调handler的.dispatchMessage(msg)方法。 3. Handler的构造方法,会首先获取当前线程的Looper对象,由于Looper对应着一个MessageQueue对象,因此这三者建立对应的关联。 4. 在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。接着我们来看一下异步消息处理的方式来更新UI线程。Handler post() new Thread(new Runnable() Override public void run() handler.post(new Runnable() Override public void run() / 在这里进行UI操作 );

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

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