源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Android 消息机制问题总结

  • 时间:2022-12-18 14:06 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Android 消息机制问题总结
Android的消息机制几乎是面试必问的话题,当然也并不是因为面试,而去学习,更重要的是它在Android的开发中是必不可少的,占着举足轻重的地位,所以弄懂它是很有必要的。下面就来说说最基本的东西。 [b]Looper[/b] 作用: 关联起Thread 循环取出消息 1、Looper是否可以直接实例化? Looper构造方法是私有的,其中做了两件事 创建一个MessageQueue 得到与之对应的Thread
private Looper(boolean quitAllowed) {
  mQueue = new MessageQueue(quitAllowed);
  mThread = Thread.currentThread();
}
[b]2、一个线程能对应多个Lopper?[/b] 不能,一个线程对应一个Looper对象,通过ThreadLocal保证一个线程只有一个Looper与之对应,如果多次调用Looper.prepare();则会抛出运行时异常。
private static void prepare(boolean quitAllowed) {
  if (sThreadLocal.get() != null) { // 查看是否有looper与当前线程对应
    throw new RuntimeException("Only one Looper may be created per thread");
  }
  sThreadLocal.set(new Looper(quitAllowed));
}
[b]3、Looper是无限循环,会阻塞吗?[/b] 是,当开启一个loop后是一个死循环,从MessageQueue中取出消息,处理消息,但是也有可能退出,在没有消息后退出循环。
public static void loop() {
  final Looper me = myLooper();
  if (me == null) {
    throw new RuntimeException("No Looper; Looper.prepare() wasn't called on   this thread.");
  }
  final MessageQueue queue = me.mQueue;
 // 略
  for (;;) {
    Message msg = queue.next(); // might block
    if (msg == null) { // 当没有消息的时候,退出
      // No message indicates that the message queue is quitting.
      return;
    }
// 略
    msg.target.dispatchMessage(msg);
  }
[b]4、可以再次调用Looper.prepareMainLooper吗?[/b] 不可以,Looper.prepareMainLooper最终也是调用prepare(),同2.
public static void prepareMainLooper() {
  prepare(false); // 创建一个Looper
  synchronized (Looper.class) {
    if (sMainLooper != null) {
      throw new IllegalStateException("The main Looper has already been   prepared.");
    }
    sMainLooper = myLooper();
  }
}
5、MainLooper什么时候创建的? MainLooper是启动Activity创建ActivityThread(并不是一个Thread)时候创建,所以不能多次创建。
public static void main(String[] args) {
 // 略
  Process.setArgV0("<pre-initialized>");
 Looper.prepareMainLooper();
 // 略
 ActivityThread thread = new ActivityThread();
 thread.attach(false);
 // 略
 if (sMainThreadHandler == null) {
  sMainThreadHandler = thread.getHandler();
 }

 // 略
 Looper.loop();
 throw new RuntimeException("Main thread loop unexpectedly exited");
 }
}

[b]Handler[/b] 作用: 发送消息到MessageQueue 处理消息 1、Handler如何与Looper、MessageQueue关联起来? 我们知道一个Looper对应一个Thread,一个Looper包含一个MessageQueue。当我们创建Handler时就会从当前线程中取出与之对应的Looper,让后在从Looper中取出MessageQueue。
// 1、自动获取
public Handler(Callback callback, boolean async) {
 // 略
  mLooper = Looper.myLooper(); // 取出当前线程中的Looper
  if (mLooper == null) {
    throw new RuntimeException(
      "Can't create handler inside thread that has not called    Looper.prepare()");
  }
  mQueue = mLooper.mQueue; // 取出MessageQueue
  mCallback = callback;
  mAsynchronous = async;
}
// 2、传递一个Looper进来
public Handler(Looper looper, Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
  }
Message 单项链表结构。 作用: 数据的载体 1、消息如何复用的? 从全局消息池(链表结构)中
public static Message obtain() {
  synchronized (sPoolSync) {
    if (sPool != null) {
      Message m = sPool;
      sPool = m.next;
      m.next = null;
      m.flags = 0; // clear in-use flag
      sPoolSize--;
      return m;
    }
  }
  return new Message();
}
[b]2、Message为什么能传递?[/b] Android中想要传递对象要么实现Serializable要么Parcelable,在这里是实现了Parcelable接口。 public final class Message implements Parcelable {   // 略 } 3、如何与Handler关联? 我们知道在消息传机制中Handler充当着“快递员”的角色,那么他又是如何与“货物”--Message发生关系呢?实际上Message有一个成员变量target他的类型正是Handler,
/*package*/ Runnable callback;

public int arg1; 

public int arg2;

public Object obj;

/*package*/ Handler target; // 关键点
当我们通过Handler去send一个Message时候最终都会为target赋值为this,即当前的Handler。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
  msg.target = this; // 赋值语句
  if (mAsynchronous) {
    msg.setAsynchronous(true);
  }
  return queue.enqueueMessage(msg, uptimeMillis);
}
另为如果是通过Message.Obtain(),获取的复用Message也会为其赋值。 多说一句,Handler.obtainMessage()调用的就是Message.Obtain()。
public final Message obtainMessage(){
  return Message.obtain(this);
}
[b]总结:[/b] 通过一系列的包涵关系,最终Looper、Handler、Message、MessageQueue即发生关联,从而形成一个闭合,开启消息循环。 [img]http://files.jb51.net/file_images/article/201608/2016826165038024.jpg?2016726165055[/img] [b]困惑[/b] 最近一直在看这方面的知识,但是能力有限,还是有不少困惑,如果有错误,或你理解下面的问题请联系我fvaryu@qq.com,愿与君交流学习,谢谢 1、Message中的sPool,哪里初始化的?为什么Message.obtain()中不会抛异常? 2、ActivityThread并不是线程,为什么可以创建一个Looper,Main Thread什么时候创建? 3、为什么序列化了的对象就可以传递?与Binder有关? 4、MessageQueue对应的是NativeMessageQueue,具体实现需要学习? 5、Loop.loop(),会退出吗?退出时机是什么?如果会退出,那么主线程同样会退出吗? 以上就是对Android 消息机制的资料整理,后续继续补充相关资料,谢谢大家对本站的支持
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部