学习Looper,handle后感
2016-08-17 20:43
288 查看
从老罗那里学习了相关知识后,自己跟随6.0的源码学习一遍。此处只为记录自己的感想和见解,有错误之处望大家指正!!!谢谢各位看官!
总体分为以下3个步骤:
1、消息循环
2、消息发送
3、消息接收处理
省略了不少无关代码。上面的代码初始化和looper ,得到了一个ActivityThread.下面具体看看代码。
frameworks/base/core/java/android/os/Looper.java
Looper.prepareMainLooper(),具体代码如下:
相关代码已经贴出来,6.0版本和2.3并没有什么区别。 这里将一个looper对象设置为唯一的主线程的looper用
sThreadLocal保存,是对象内的变量。这里quitAllowed=false。然后初始化了一个messageQueue.下面看下这个消息队列:处于同一目录
这里将生成的nativeMessageQueue进行了加工,返回给java层,用ptr 保存了这个对应关系。下面贴下如何new NativeMessageQueue()
总体分为以下3个步骤:
1、消息循环
2、消息发送
3、消息接收处理
1、消息循环
一、初始化Process.setArgV0("<pre-initialized>"); ................. Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop();
省略了不少无关代码。上面的代码初始化和looper ,得到了一个ActivityThread.下面具体看看代码。
frameworks/base/core/java/android/os/Looper.java
Looper.prepareMainLooper(),具体代码如下:
/** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
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)); }
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
相关代码已经贴出来,6.0版本和2.3并没有什么区别。 这里将一个looper对象设置为唯一的主线程的looper用
sThreadLocal保存,是对象内的变量。这里quitAllowed=false。然后初始化了一个messageQueue.下面看下这个消息队列:处于同一目录
MessageQueue(boolean quitAllowed) { mQuitAllowed = quitAllowed; mPtr = nativeInit(); }这里调用了JNI,
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进行了加工,返回给java层,用ptr 保存了这个对应关系。下面贴下如何new NativeMessageQueue()
NativeMessageQueue::NativeMessageQueue() : mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) { mLooper = Looper::getForThread(); if (mLooper == NULL) { mLooper = new Looper(false); Looper::setForThread(mLooper); } }Looper目录在:system/core/libutils/Looper.cpp 注意大小写区分
Looper::Looper(bool allowNonCallbacks) : mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false), mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false), mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) { mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd: %s", strerror(errno)); AutoMutex _l(mLock); rebuildEpollLocked(); }
void Looper::rebuildEpollLocked() { // Close old epoll instance if we have one. if (mEpollFd >= 0) { #if DEBUG_CALLBACKS ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this); #endif close(mEpollFd); } // Allocate the new epoll instance and register the wake pipe. mEpollFd = epoll_create(EPOLL_SIZE_HINT); LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno)); struct epoll_event eventItem; memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union eventItem.events = EPOLLIN; eventItem.data.fd = mWakeEventFd; int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem); LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance: %s", strerror(errno)); for (size_t i = 0; i < mRequests.size(); i++) { const Request& request = mRequests.valueAt(i); struct epoll_event eventItem; request.initEventItem(&eventItem); int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem); if (epollResult < 0) { ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s", request.fd, strerror(errno)); } } }
2、消息发送
3、消息接收处理
相关文章推荐
- 【docker】docker容器的网络基础
- 监控CPU(二)
- Tomcat在CentOS6.7上的安装配置及使用
- linux相关应当尽量避免的命令,操作及设置
- shell 脚本之 for,while,until
- linux--wget命令
- 修改了jsp内容,但是运行在tomcat中没有变化
- CentOS下搭建个人Python开发环境
- 在Linux中查看文件的编码及对文件进行编码转换
- 在项目什么时候选择使用GCD,什么时候选择NSOperation?
- Tomcat 404问题详解
- linux常用命令总结
- linux--source命令
- UVA | Optimal Binary Search Tree
- Docker
- Opencv学习笔记(五)--形态学操作
- linux 批量复制某一类文件shell脚本
- Linux 如何在 vi 里搜索关键字(Xshell)
- 【docker安装】docker安装与部署
- shell 2 俄罗斯方块