阅读更多

0顶
0踩

编程语言

转载新闻 深入理解Android消息机制

2018-04-20 11:18 by 副主编 jihong10102006 评论(0) 有24207人浏览
在日常的开发中,Android 的消息机制作为系统运行的根本机制之一,显得十分的重要。
从 Handler 发送消息开始

查看源码,Handler的post、send方法最终都会走到
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
sendMessageDelayed 会走到
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
这里可以设置 Message 为异步消息

查看 queue 的 enqueueMessage 方法, 我们剥离出核心代码:
if (p == null || when == 0 || when < p.when) { // New head, wake up the event queue if blocked. msg.next = p; mMessages = msg; needWake = mBlocked; }
如果是新的队列头,直接插入队列

如果队列里面已经有消息了,执行如下逻辑
needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { needWake = false; } } msg.next = p; // invariant: p == prev.next prev.next = msg;
插入消息的时候,一般不会唤醒消息队列。如果消息是异步的,并且队列头不是一个异步消息的时候,会唤醒消息队列
if (needWake) { nativeWake(mPtr); }
消息队列的具体唤醒过程我们暂时不细看。把关注点移到 Looper 上。looper在执行的时候具体执行了什么逻辑呢?查看 Looper.java 的 looper() 方法

looper 方法中有一个死循环, 在死循环中,会获取下一个 Message
for (;;) { Message msg = queue.next(); // might block }
if (msg != null && msg.target == null) { // Stalled by a barrier. Find the next asynchronous message in the queue. do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous());
当存在一个 barrier 消息的时候,会寻找队列中下一个异步任务。而不是按照顺序。 例如3个消息,1,2,3, 2 是异步消息。如果不存在barrier的时候,next的顺序就是 1,2,3 但是如果存在barrier的时候,则是 2,1,3
if (msg != null) { if (now < msg.when) { // Next message is not ready. Set a timeout to wake up when it is ready. nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { // Got a message. mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; if (DEBUG) Log.v(TAG, "Returning message: " + msg); msg.markInUse(); return msg; } } else { // No more messages. nextPollTimeoutMillis = -1; }
这里如果 next 的 Message 不为空,就返回,并且将它移出队列 在 MessageQueue 为空的时候,会顺便去处理一下 add 过的 IdleHandler, 处理一些不重要的消息
for (int i = 0; i < pendingIdleHandlerCount; i++) { final IdleHandler idler = mPendingIdleHandlers[i]; mPendingIdleHandlers[i] = null; // release the reference to the handler boolean keep = false; try { keep = idler.queueIdle(); } catch (Throwable t) { Log.wtf(TAG, "IdleHandler threw exception", t); } if (!keep) { synchronized (this) { mIdleHandlers.remove(idler); } }
查看 IdleHandler 的源码。
    * Callback interface for discovering when a thread is going to block * waiting for more messages. */ public static interface IdleHandler { /** * Called when the message queue has run out of messages and will now * wait for more. Return true to keep your idle handler active, false * to have it removed. This may be called if there are still messages * pending in the queue, but they are all scheduled to be dispatched * after the current time. */ boolean queueIdle(); }
当 queueIdle() 为 false 的时候,会将它从 mIdleHandlers 中 remove,仔细思考下,我们其实可以利用IdleHandler实现不少功能, 例如
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { @Override public boolean queueIdle() { return false } });
我们可以在 queueIdle 中,趁着没有消息要处理,统计一下页面的渲染时间(消息发送完了说明UI已经渲染完了),或者算一下屏幕是否长时间没操作等等。

拿到 Message 对象后,会将 Message 分发到对应的 target 去
msg.target.dispatchMessage(msg);
查看源码
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
当 msg 的 callback 不为 null 的时候,即通过 post(Runnable) 发送信息的会执行 handlerCallback(msg) 方法。如果 mCallback 不为 null并且 handleMessage 的结果为 false,则执行 handleMessage 方法。否则会停止分发。
private static void handleCallback(Message message) { message.callback.run(); }
查看 handlerCallback 方法源码, callback 会得到执行。到这里基本的Android消息机制就分析完了,简而言之就是,Handler 不断的将Message发送到一 根据时间进行排序的优先队列里面,而线程中的 Looper 则不停的从MQ里面取出消息,分发到相应的目标Handler执行。

为什么主线程不卡?

分析完基本的消息机制,既然 Looper 的 looper 方法是一个for(;;;)循环,那么新的问题提出来了。为什么Android会在主线程使用死循环?执行死循环的时候为什么主线程的阻塞没有导致CPU占用的暴增?�

继续分析在源码中我们没有分析的部分:
  • 消息队列构造的时候是否调用了jni部分
  • nativeWake、nativePollOnce这些方法的作用是什么
先查看MQ的构造方法:
MessageQueue(boolean quitAllowed) { mQuitAllowed = quitAllowed; mPtr = nativeInit(); }
会发现消息队列还是和native层有关系,继续查看android/platform/frameworks/base/core/jni/android_os_MessageQueue_nativeInit.cpp中nativeInit的实现:
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) { NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue(); if (!nativeMessageQueue) { jniThrowRuntimeException(env, "Unable to allocate native queue"); return 0; } nativeMessageQueue->incStrong(env); return reinterpret_cast<jlong>(nativeMessageQueue); }
这里会发现我们初始化了一个 NativeMessageQueue ,查看这个消息队列的构造函数
NativeMessageQueue::NativeMessageQueue() : mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) { mLooper = Looper::getForThread(); if (mLooper == NULL) { mLooper = new Looper(false); Looper::setForThread(mLooper); } }
这里会发现在mq中初始化了 native 的 Looper 对象,查看android/platform/framework/native/libs/utils/Looper.cpp中 Looper 对象的构造函数
// 简化后的代码 Looper::Looper(bool allowNonCallbacks) : mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) { int wakeFds[2]; int result = pipe(wakeFds); mWakeReadPipeFd = wakeFds[0]; mWakeWritePipeFd = wakeFds[1]; result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); mEpollFd = epoll_create(EPOLL_SIZE_HINT); struct epoll_event eventItem; memset(& eventItem, 0, sizeof(epoll_event)); eventItem.events = EPOLLIN; eventItem.data.fd = mWakeReadPipeFd; result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); }
这里我们会发现,在 native 层创建了一个epoll,并且对 epoll 的 event 事件进行了监听。

什么是epoll

在继续分析源码之前,我们先分析一下,什么是epoll

epoll是Linux中的一种IO多路复用方式,也叫做event-driver-IO。

Linux的select 多路复用IO通过一个select()调用来监视文件描述符的数组,然后轮询这个数组。如果有IO事件,就进行处理。

select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大,其复制的开销也线性增长。

epoll在select的基础上(实际是在poll的基础上)做了改进,epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可。

另一个本质的改进在于epoll采用基于事件的就绪通知方式(设置回调)。在select中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知

关于epoll和select,可以举一个例子来表达意思。select的情况和班长告诉全班同学交作业类似,会挨个去询问作业是否完成,如果没有完成,班长会继续询问。

而epoll的情况则是班长询问的时候只是统计了待交作业的人数,然后告诉同学作业完成的时候告诉把作业放在某处,然后喊一下他。然后班长每次都去这个地方收作业。

大致了解了epoll之后,我们继续查看nativePollOnce方法,同理,会调用native Looper的pollOnce方法
while (mResponseIndex < mResponses.size()) { const Response& response = mResponses.itemAt(mResponseIndex++); int ident = response.request.ident; if (ident >= 0) { int fd = response.request.fd; int events = response.events; void* data = response.request.data; if (outFd != NULL) *outFd = fd; if (outEvents != NULL) *outEvents = events; if (outData != NULL) *outData = data; return ident; } }
在pollOnce中,会先处理没有callback的response(ALOOPER_POLL_CALLBACK = -2),处理完后会执行pollInner方法
// 移除了部分细节处理和日志代码 // 添加了分析源码的日志 int Looper::pollInner(int timeoutMillis) { if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime); if (messageTimeoutMillis >= 0 && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) { timeoutMillis = messageTimeoutMillis; } } // Poll. int result = ALOOPER_POLL_WAKE; mResponses.clear(); mResponseIndex = 0; struct epoll_event eventItems[EPOLL_MAX_EVENTS]; // 等待事件发生或者超时 int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); // Acquire lock. mLock.lock(); // Check for poll error. // epoll 事件小于0, 发生错误 if (eventCount < 0) { if (errno == EINTR) { goto Done; } result = ALOOPER_POLL_ERROR; goto Done; } if (eventCount == 0) { // epoll事件为0,超时,直接跳转到Done result = ALOOPER_POLL_TIMEOUT; goto Done; } //循环遍历,处理所有的事件 for (int i = 0; i < eventCount; i++) { int fd = eventItems[i].data.fd; uint32_t epollEvents = eventItems[i].events; if (fd == mWakeReadPipeFd) { if (epollEvents & EPOLLIN) { awoken(); //唤醒,读取管道里面的事件 } else { } } else { ssize_t requestIndex = mRequests.indexOfKey(fd); if (requestIndex >= 0) { int events = 0; // 处理request,生成response对象,push到相应的Vector pushResponse(events, mRequests.valueAt(requestIndex)); } else { } } } Done: ; // Invoke pending message callbacks. // 发生超时的逻辑处理 mNextMessageUptime = LLONG_MAX; while (mMessageEnvelopes.size() != 0) { // 处理Native端的Message nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0); if (messageEnvelope.uptime <= now) { // Remove the envelope from the list. // We keep a strong reference to the handler until the call to handleMessage // finishes. Then we drop it so that the handler can be deleted *before* // we reacquire our lock. { // obtain handler sp<MessageHandler> handler = messageEnvelope.handler; Message message = messageEnvelope.message; mMessageEnvelopes.removeAt(0); mSendingMessage = true; mLock.unlock(); handler->handleMessage(message); // 处理消息事件 } // release handler mLock.lock(); mSendingMessage = false; result = ALOOPER_POLL_CALLBACK; // 设置回调 } else { // The last message left at the head of the queue determines the next wakeup time. mNextMessageUptime = messageEnvelope.uptime; break; } } // Release lock. mLock.unlock(); // Invoke all response callbacks. // 执行回调 for (size_t i = 0; i < mResponses.size(); i++) { Response& response = mResponses.editItemAt(i); if (response.request.ident == ALOOPER_POLL_CALLBACK) { int fd = response.request.fd; int events = response.events; void* data = response.request.data; int callbackResult = response.request.callback->handleEvent(fd, events, data); if (callbackResult == 0) { removeFd(fd); //移除fd } // Clear the callback reference in the response structure promptly because we // will not clear the response vector itself until the next poll. response.request.callback.clear(); // 清除reponse引用的回调方法 result = ALOOPER_POLL_CALLBACK; // 发生回调 } } return result; }
看到这里,我们其实可以看出来整体消息模型由 native 和 Java 2层组成,2层各自有自己的消息系统。 Java层通过调用 pollonce 来达到调用底层epoll 让死循环进入阻塞休眠的状态,以避免浪费CPU, 所以这也解释了为什么Android Looper的死循环为什么不会让主线程CPU占用率飙升。

java层和native层的对应图如下:

备注
  • Java 层和 native 层通过 MessageQueue 里面持有一个 native 的MessageQueue 对象进行交互。WeakMessageHandler 继承自MessageHandler,NativeMessageQueue 继承自 MessageQueue
  • Java 层和 native 层实质是各自维护了一套相似的消息系统。C层发出的消息和Java层发出的消息可以没有任何关系。所以 Framework 层只是很巧的利用了底层 epoll 的机制达到阻塞的目的。
  • 通过 pollOnce 的分析,可以发现消息的处理其实是有顺序的,首先是处理native message,然后处理native request,最后才会执行java层,处理java层的message
可以在子线程中创建Handler吗?为什么每个线程只会有一个Looper?

在很多时候,我们可以遇到这2个问题。既然看了 Handler 的源码,那么,我们就顺便分析一下这 2 个问题。

查看Handler的构造方法,无参构造方法最后会调用
public Handler(Callback callback, boolean async) { mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
可以看到,这里会直接获取Looper
public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
这里会把每个 Looper 存到相应的ThreadLocal对象中,如果子线程直接创建了Handler,Looper 就会是一个null,所以会直接跑出一个"Can't create handler inside thread that has not called Looper.prepare()"的RuntimeException

那么我们是何时把Looper放入ThreadLocal对象的呢?可以在Looper.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)); }
这也解释了,在每个 Thread 中,只会存在一个 Looper 对象。如果我们想在子线程中正常创建 Handler,就需要提前运行当前线程的 Looper,调用
Looper.prepare()
就不会抛出异常了。

总结

消息机制作为 Android 的基础,还是非常有深入了解的必要。对于我们遇到Handler发送消息的时候跑出的系统异常的排查也很有意义。

特别感谢

本次源码的阅读过程中,遇到了很多不了解的问题例如epoll,这里非常感谢IO哥(查看IO哥大佬)助和指导。让我在某些细节问题上暂时绕过和恍然大悟。
  • 大小: 13.9 KB
来自: github
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • android消息机制 android 消息机制 深入理解android消息机制 更好开发
  • 从源码深入理解Android Handler异步消息处理机制
  • 深入理解android消息机制
  • 深入理解android 消息机制
  • android 深入理解Android消息机制
  • 深入理解Android 消息机制(一)——综述 在日常开发和学习中,我们肯定都会接触到Android消息机制。我们知道,在非UI线程中不能直接更新UI,一般我们都是在非UI线程中通过Handler发送一条消息来更新UI。通过Handler可以将任务切换到Handler所在的线程中。Android消息机制主要是指Handler的运行机制,Handler的运行需要和MessageQueue和Looper配合才能完成。可能有人会问:我在Activity
  • 深入理解Android Handler 消息机制
  • 深入理解android消息机制(四)——消息队列延时机制(很有趣)
  • Android消息机制——深入理解Handler
  • 深入理解Android Wi-Fi,NFC和GPS卷》作者邓凡平CSDN博客
  • 深入理解ANDROID 卷3高清完整PDF版 深入理解Android(卷3)》是Android经典畅销书系“深入理解Android”系列Framework卷的第III卷,从源代码的角度,对Android系统的Audio和UI两大功能的相关模块的实现原理和工作机制做了系统且详细的分析,填补了市场的空白。   《深入理解Android(卷3)》在逻辑上分为4个部分:   Part 01(第1~2章):这是本书的基础部分,首先介绍了Android源码环境的搭建、编译和调试;然后讲解了Android进程间通信与任务调度的工具Binder与MessageQueue。这两项基础工作是深入研究Android前必须做的功课。   Part 02(第3章):详细分析了AudioService服务的实现,包括音量管理、音频外设管理、AudioFocus机制的实现等内容。   Part 03(第4~6章):这是本书的核心内容之一,详细分析了Android UI的通用实现,依次剖析了WindowManagerService、Android输入系统、Android控件系统的工作原理。   Part 04(第7~8章):主要分析了SystemUI和Android壁纸相关服务的实现,包括StatusBarManagerService与NotificationManagerService两个系统服务,以及WallpaperManagerService系统服务、动态壁纸与静态壁纸的工作原理等内容。   除此之外,在对海量的Android源代码进行分析的过程中,本书尽可能地对其中的精妙之处进行了分析和解读,目的是希望帮助读者领悟其中的优秀设计思想和方法。
  • 深入理解Android Wi-Fi,NFC和GPS卷 全面到货
  • 深入理解Android卷3_高清PDF版 本书适合Android系统级开发人员,重点在底层和框架层,这是深入理解Android的第3卷。本书为完整扫描版,文字清晰,排版整齐,整体文件经过压缩,体积更小,去除了多余重复页面。并且纠正了错误的标签,欢迎对android系统架构感兴趣的朋友下载。
  • https://download.csdn.net/download/lcl497049972/10446876
  • 【下载】深入理解android系列书籍pdf(卷1,卷2,卷3,卷4) 深入理解android系列书籍pdf(卷1,卷2,卷3,卷4) 下载链接: https://pan.baidu.com/s/1zQ7IeYOr3uKwSwWTeSkxtQ  提取码获取方式:扫描关注下面微信公众号,回复关键字: deandroid ...
  • 深入理解Android卷1.pdf
  • 深入理解Android(卷2)(带全目录完整版)邓凡平.pdf 内容简介 《深入理解android:卷ii》是“深入理解android”系列的第二本,第一本书上市后得到了广大读者的高度评价,在android开发者社群内口口相传。本书不仅继承了第一本的优点、改正了其在细微处存在的一些不足,而且还在写作的总体思想上进行了创新,更强调从系统设计者的角度去分析android系统中各个模块内部的实现原理和工作机制。从具体内容上讲,本书的重点是android framework的java层,对java层涉及的核心模块和服务进行了深入而细致的分析。通过本书,读者不仅能对android系统本身有更深入的理解,而且还能掌握分析大型复杂源代码的能力。   全书共8章:第1章介绍了阅读本书所需要做的准备工作,包括android 4.0源码的下载和编译、eclipse环境的搭建,以及android系统进程(system_process)的调试等;第2章对java binder和messagequeue的实现进行了深入分析;第3章详细剖析了systemserver的工作原理,这些服务包括entropyservice、dropboxmanagerservice、diskstatsservice、devicestoragemonitorservice、samplingprofilerservice和clipboardservice;第4章对系统中负责package信息查询和apk安装、卸载、更新等工作的服务packagemanagerservice进行了详细分析;第5章则对android系统中负责电源管理的核心服务 powermanagerservice的原理进行了一番深入的分析;第6章以activitymanagerservice为分析重点,对它的启动、activity的创建和启动、broadcastreceiver的工作原理、android中的进程管理等内容展开了较为深入的研究;第7章对contentprovider的创建和启动、sqlite、cursor query和close的实现等进行了深入分析;第8章以contentservice和accountmanagerservice为分析对象,介绍了数据更新通知机制的实现,以及账户管理和数据同步等相关知识。 目录 《深入理解android:卷ii》 前 言 第1章 搭建android源码工作环境 / 1 1.1 android系统架构 / 2 1.2 搭建开发环境 / 3 1.2.1 下载源码 / 3 1.2.2 编译源码 / 4 1.2.3 利用eclipse调试system_process / 5 1.3 本章小结 / 11 第2章 深入理解java binder和messagequeue / 12 2.1 概述 / 13 2.2 java层中的binder架构分析 / 13 2.2.1 binder架构总览 / 13 2.2.2 初始化java层binder框架 / 14 2.2.3 addservice实例分析 / 17 2.2.4 java层binder架构总结 / 26 2.3 心系两界的messagequeue / 27 2.3.1 messagequeue的创建 / 27 2.3.2 提取消息 / 28 2.3.3 nativepollonce函数分析 / 31 2.3.4 messagequeue总结 / 41 2.4 本章小结 / 42 第3章 深入理解systemserver / 44 3.1 概述 / 45 3.2 systemserver分析 / 45 3.2.1 main函数分析 / 45 3.2.2 service群英会 / 48 3.3 entropyservice分析 / 49 3.4 dropboxmanagerservice分析 / 50 3.4.1 dbms构造函数分析 / 51 3.4.2 dropbox日志文件的添加 / 51 3.4.3 dbms和settings数据库 / 56 3.5 diskstatsservice和devicestoragemonitorservice分析 / 56 3.5.1 diskstatsservice分析 / 56 3.5.2 devicestoragemanagerservice分析 / 58 3.6 samplingprofilerservice分析 / 60 3.6.1 samplingprofilerservice构造函数分析 / 61 3.6.2 samplingprofilerintegration分析 / 62 3.7 clipboardservice分析 / 64 3.7.1 复制数据到剪贴板 / 64 3.7.2 从剪切板粘贴数据 / 67 3.7.3 cbs中的权限管理 / 69 3.8 本章小结 / 73 第4章 深入理解packagemanagerservice / 74 4.1 概述 / 75 4.2 初识packagemanagerservice / 76 4.3 pkms的main函数分析 / 77 4.3.1 构造函数分析之前期准备工作 / 78 4.3.2 构造函数分析之扫描package / 90 4.3.3 构造函数分析之扫尾工作 / 105 4.3.4 pkms构造函数总结 / 105 4.4 apk installation分析 / 105 4.4.1 adb install分析 / 105 4.4.2 pm分析 / 107 4.4.3 installpackagewithverification函数分析 / 109 4.4.4 apk 安装流程总结 / 121 4.4.5 verification介绍 / 122 4.5 queryintentactivities分析 / 124 4.5.1 intent及intentfilter介绍 / 124 4.5.2 activity信息的管理 / 125 4.5.3 intent 匹配查询分析 / 128 4.5.4 queryintentactivities总结 / 131 4.6 installd及usermanager介绍 / 131 4.6.1 installd介绍 / 131 4.6.2 usermanager介绍 / 136 4.7 本章学习指导 / 138 4.8 本章小结 / 138 第5章 深入理解powermanagerservice / 139 5.1 概述 / 140 5.2 初识powermanagerservice / 140 5.2.1 pms构造函数分析 / 141 5.2.2 init分析 / 141 5.2.3 systemready分析 / 147 5.2.4 bootcomplete处理 / 148 5.2.5 初识powermanagerservice总结 / 149 5.3 pms wakelock分析 / 149 5.3.1 wakelock客户端分析 / 149 5.3.2 pms acquirewakelock分析 / 151 5.3.3 power类及lightservice类介绍 / 160 5.3.4 wakelock总结 / 163 5.4 useractivity及power按键处理分析 / 164 5.4.1 useractivity分析 / 164 5.4.2 power按键处理分析 / 167 5.5 batteryservice及batterystatsservice分析 / 168 5.5.1 batteryservice分析 / 169 5.5.2 batterystatsservice分析 / 172 5.5.3 batteryservice及batterystatsservice总结 / 182 5.6 本章学习指导 / 183 5.7 本章小结 / 183 第6章 深入理解activitymanagerservice / 184 6.1 概述 / 185 6.2 初识activitymanagerservice / 186 6.2.1 activitymanagerservice的main函数分析 / 187 6.2.2 ams的 setsystemprocess分析 / 197 6.2.3 ams的 installsystemproviders函数分析 / 202 6.2.4 ams的 systemready分析 / 211 6.2.5 初识activitymanagerservice总结 / 218 6.3 startactivity分析 / 219 6.3.1 从am说起 / 219 6.3.2 ams的startactivityandwait函数分析 / 221 6.3.3 startactivitylocked分析 / 230 6.4 broadcast和broadcastreceiver分析 / 265 6.4.1 registerreceiver流程分析 / 267 6.4.2 sendbroadcast流程分析 / 272 6.4.3 broadcast_intent_msg消息处理函数 / 276 6.4.4 应用进程处理广播分析 / 282 6.4.5 广播处理总结 / 284 6.5 startservice之按图索骥 / 285 6.5.1 service知识介绍 / 285 6.5.2 startservice流程图 / 286 6.6 ams中的进程管理 / 287 6.6.1 linux进程管理介绍 / 287 6.6.2 关于android中的进程管理的介绍 / 289 6.6.3 ams进程管理函数分析 / 294 6.6.4 ams进程管理总结 / 305 6.7 app的 crash处理 / 305 6.7.1 应用进程的crash处理 / 306 6.7.2 ams的handleapplicationcrash分析 / 306 6.7.3 appdeathrecipient binderdied分析 / 309 6.7.4 app的crash处理总结 / 313 6.8 本章学习指导 / 314 6.9 本章小结 / 315 第7章 深入理解contentprovider / 316 7.1 概述 / 317 7.2 mediaprovider的启动及创建 / 318 7.2.1 context的getcontentresolver函数分析 / 318 7.2.2 mediastore.image.media的query函数分析 / 319 7.2.3 mediaprovider的启动及创建总结 / 329 7.3 sqlite创建数据库分析 / 330 7.3.1 sqlite及sqlitedatabase家族 / 330 7.3.2 mediaprovider创建数据库分析 / 335 7.3.3 sqlitedatabase创建数据库的分析总结 / 344 7.4 cursor 的query函数的实现分析 / 345 7.4.1 提取query关键点 / 346 7.4.2 mediaprovider 的query分析 / 349 7.4.3 query关键点分析 / 356 7.4.4 cursor query实现分析总结 / 368 7.5 cursor close函数实现分析 / 368 7.5.1 客户端close的分析 / 369 7.5.2 服务端close的分析 / 371 7.5.3 finalize函数分析 / 372 7.5.4 cursor close函数总结 / 373 7.6 contentresolver openassetfiledescriptor函数分析 / 373 7.6.1 openassetfiledescriptor之客户端调用分析 / 374 7.6.2 contentprovider的 opentypedassetfile函数分析 / 376 7.6.3 跨进程传递文件描述符的探讨 / 379 7.6.4 openassetfiledescriptor函数分析总结 / 384 7.7 本章学习指导 / 384 7.8 本章小结 / 385 第8章 深入理解contentservice和accountmanagerservice / 386 8.1 概述 / 387 8.2 数据更新通知机制分析 / 387 8.2.1 初识contentservice / 388 8.2.2 contentresovler 的registercontentobserver分析 / 389 8.2.3 contentresolver的 notifychange分析 / 391 8.2.4 数据更新通知机制总结和深入探讨 / 393 8.3 accountmanagerservice分析 / 395 8.3.1 初识accountmanagerservice / 396 8.3.2 accountmanager addaccount分析 / 402 8.3.3 accountmanagerservice的分析总结 / 414 8.4 数据同步管理syncmanager分析 / 415 8.4.1 初识syncmanager / 415 8.4.2 contentresolver 的requestsync分析 / 424 8.4.3 数据同步管理syncmanager分析总结 / 436 8.5 本章学习指导 / 437 8.6 本章小结 / 437 “深入理解android”系列书籍的规划路线图 / 438
  • 深入理解Android 卷III》推荐序 深入理解Android 卷III》即将发布,作者是张大伟。此书填补了深入理解Android Framework卷中的一个主要空白,即Android Framework中和UI相关的部分。在一个特别讲究颜值的时代,本书分析了Android 4.2中WindowManagerService、ViewRoot、Input系统、StatusBar、Wallpaper等重要“颜值绘制/处理”模块推荐序回顾
  • 深入理解Android:卷1》- Android架构
  • [深入理解Android卷一全文-第一章]阅读前的准备工作 由于《深入理解Android 卷一》和《深入理解Android卷二》不再出版,而知识的传播不应该因为纸质媒介的问题而中断,所以我将在CSDN博客中全文转发这两本书的全部内容。(出版社排版好的PDF版正在向出版社申请,到时候会通过CSDN下载资源发布)第一章  阅读前的准备工作本章主要内容本章简单介绍Android系统架构、编译环境的搭建以及一些工具的使用。1.1  系统架构1.1.1  Andro
Global site tag (gtag.js) - Google Analytics