接触安卓几年了。但是感觉一直不是很明白,东西太多了。反过来说就是自己太菜了。很多东西其实都是模凌两可,不熟悉,很多知识点都是知道一点,最多大家都这样用。没问题,事件长了也一直这样用的。
但是有个问题,安卓在不断的升级,但是自己的知识却升的不多。咋整? 想去全球顶级公司不? 想, 想去是好。但是得把软件开发的路子或者思想弄透彻了。得把实现机制弄懂了。这样估计就用机会了。

我们今天来谈谈Handler Looper Messagequeue的知识。这个东西是入门的东西,也是写安卓应用必备的知识点。但是我怎么感觉还不透彻了。实在不透彻。不管别人怎么样,反正我记录下,最好能学会。

多个handler绑定了一个Looper, 一个looper绑定了一个MessageQueue 臧春杰 marvell 这个都知道。 也知道java通过线程私有变量来保存looper信息。 也就是说一个线程最多有个一个Looper. 系统通过ThreadLocal方法来保存

线程私有变量。

那下面一步就是冲消息队列取消息然后处理消息,如果没有消息就再等待。

我们通过代码可以看到,
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
诡异了。这里有个jni方法,莫非消息队列是通过jni建立的?
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz //臧春杰 marvell) {
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() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
这里出现了我们的主角,这里需要问一句, 线程在消息队列没有消 臧春杰 marvell 息的时候会阻塞,那如何阻塞呢? 是阻塞在java里的吗? 是阻塞这哪里的呢? 可以说就是阻塞在looper里,这里looper.cpp不要和Java层的Looper.java混淆了。

这两个东西毫无关系,记得是毫无关系,陌生人,谁也不认识谁。
那c++这里是如何阻塞的呢? epoll多路监听阻塞,那阻塞的描述符是哪个呢?Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false), //臧春杰 marvell
mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
mWakeEventFd = eventfd(0, EFD_NONBLOCK);

mWakeEventFd = eventfd(0, EFD_NONBLOCK);就这个,套路啊。慢慢的全是套路,以前不是用pipe的吗?时代在进步,社会在发展,用了eventfd了。

那这就明白了,looper在epoll_wait等待唤醒。那紧接着问题来了,我们经常使用比如5秒后唤醒,那这5秒是如何做到呢?系统如何计时5秒呢?同样也是epoll_wait参 臧春杰 marvell数有个timeout用来计时,
epoll_wait返回值需要说明下。
When successful, epoll_wait() returns the number of file descriptors ready for the requested I/O, or zero if no file
descriptor became ready during the requested timeout milliseconds. When an error occurs, epoll_wait() returns -1 and
errno is set appropriately.
这就是问题的关键。

其实在c++层面,也可以处理消息,也可以监听文件描述符。
int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data);
void sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
const Message& message); 臧春杰 marvell
所以我们可以看到,很多在native service中,都使用了这些功能。

那既然在c++层面在监听,那如何唤醒呢? 很简单,就是让文件描述符可读,如何可读? 往文件描述符写东西

void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ wake", this);
#endif

uint64_t inc = 1;
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
if (nWrite != sizeof(uint64_t)) {
if (errno != EAGAIN) {
ALOGW("Could not write wake signal, errno=%d", errno);
}
}
}
通过这个东西,可以唤醒了。开始做消息处理。这就是为什么消息先处理c++层面的消息,然后再处理java层面的消息。所有的消息处理都根据消息的触发时间来计算的。看当前时间和消息需要触发时间比较。

通过这两个时间来计算timeout时间,这就要求消息队列是排序的,按照触发时间排序。

消息队列补充知识点:

我们听说过桩子臧春杰 marvell的概念。postSyncBarrier,removeSyncBarrier 这个是干什么用呢? 桩子的作用是 桩子后面的消息系统不会处理,直到桩子被拿掉,这是干什么呢?

想想这个场景,我们在主线程干事情,往另一个线程发消息,但是我们得主线程干完,其他线程才能处理消息,那如何保证这个呢? 这就需要桩子,不然cpu 臧春杰 marvell 调度时候,我们不能保证这个消息在什么时候处理。说不定,

sendMessage后,它立马就运行了。

当消息队列没有消息时候,我们可以做点其他事情,
addIdleHandler

我一般用他来做垃圾回收。

android MessageQueue入门的更多相关文章

  1. [译]:Xamarin.Android开发入门——Hello,Android Multiscreen深入理解

    原文链接:Hello, Android Multiscreen_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android Multiscreen深入理解. 本 ...

  2. [译]:Xamarin.Android开发入门——Hello,Android深入理解

    返回索引目录 原文链接:Hello, Android_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android深入理解 本部分介绍利用Xamarin开发And ...

  3. [译]:Xamarin.Android开发入门——Hello,Android快速上手

    返回索引目录 原文链接:Hello, Android_Quickstart. 译文链接:Xamarin.Android开发入门--Hello,Android快速上手 本部分介绍利用Xamarin开发A ...

  4. Hello, Android 快速入门

    Hello, Android Android 开发与 Xamarin 简介 在这两节指南中,我们将 (使用 Xamarin Studio或 Visual Studio)建立我们的第一个 Xamarin ...

  5. Android工程师入门(二)——不忙不累怎么睡。。

    安卓开发迫在眉睫,这周入个门吧! Android工程师入门(二) 四.在界面中显示图片 ImageView 是显示图片的一个控件. --属性 src——内容图片: background——背景图片/背 ...

  6. [电子书] 《Android编程入门很简单》

    <Android编程入门很简单>是一本与众不同的Android学习读物,是一本化繁为简,把抽象问题具体化,把复杂问题简单化的书.本书避免出现云山雾罩.晦涩难懂的讲解,代之以轻松活泼.由浅入 ...

  7. Android实现入门界面布局

    Android实现入门界面布局 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 代码实现 首先是常量的定义,安卓中固定字符串应该定义在常量中. stri ...

  8. Android从入门到精通pdf+书源代码

    不须要积分,免费放送 Android从入门到精通的pdf,入门的好书籍,因为csdn文件大小的限制所以分成了两部分. part1地址:http://download.csdn.net/detail/a ...

  9. 教我徒弟Android开发入门(一)

    前言: 这个系列的教程是为我徒弟准备的,也适合还不懂java但是想学android开发的小白们~ 本系列是在Android Studio的环境下运行,默认大家的开发环境都是配置好了的 没有配置好的同学 ...

随机推荐

  1. 轻松搭建docker应用的mesos集群

    7条命令在docker中部署Mesos集群 所有使用的Docker容器构建文件是有也.您可以在本地构建每个容器或只使用位于Docker Hub预构建的容器.下面的命令会自动下载所需的预建的容器为您服务 ...

  2. Mishka and Interesting sum

    Mishka and Interesting sum time limit per test 3.5 seconds memory limit per test 256 megabytes input ...

  3. LightOJ 1282 Leading and Trailing 数论

    题目大意:求n^k的前三位数 和 后三位数. 题目思路:后三位数直接用快速幂取模就行了,前三位则有些小技巧: 对任意正数都有n=10^T(T可为小数),设T=x+y,则n=10^(x+y)=10^x* ...

  4. 使用jquery的js的页面实现例子

    var validate;var nodeId="";var modifyappId=""; addExportTaskURL = ctx + "/x ...

  5. HDU 2802 F(N)(简单题,找循环解)

    题目链接 F(N) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  6. AI 人工智能 探索 (六)

    这次我为 角色 attribute 添加了 多个属性 其中 att 是 好人 坏人 等属性, 显然 数字不同 就要打起来. grade 是智商属性 ,今天先做了 3的智商.也就是小兵智商.碰到就打 逃 ...

  7. mytest 截图

  8. ERROR: No pool defined. at least one pool section must be specified in config file

    root@ubuntu:/opt/php7# /opt/php7/sbin/php-fpm [22-Sep-2015 14:29:00] WARNING: Nothing matches the in ...

  9. iis7支持asp(访问页面,页面存在仍然提示404)

    1. win7下安装IIS时ASP一般被默认不选中的状态,因此需要打开IIS检查功能视图栏中是否存在ASP选项,若没有则需要从控制面板->程序和 功能->打开或关闭Windows功能-&g ...

  10. 励研(LY) CRC16算法

    /**************************************************** ** 函数名称: CalculateCRC16 ** 输 入: buf 要校验的数据; le ...