zoukankan      html  css  js  c++  java
  • Android 9.0 Native Looper机制(应用篇)

    * 站在巨人的肩膀上可以看的更远 *

    Android 9.0 Native Looper机制(原理篇)

    Android 9.0 Native Looper机制(应用篇)

    前言

    上一篇中我们简单分析了Android Native Looper机制的基本运行过程,这一篇就是在此基础上给出一个具体使用的例子。通过这个例子来具体看如何发送消息,处理消息

    代码

    直接上代码,如下

    //
    // Copyright 2010 The Android Open Source Project
    //
    //#define LOG_NDEBUG 0
      #define LOG_TAG "LooperTest"
    
    #include <utils/Looper.h>
    #include <utils/Timers.h>
    #include <utils/Log.h>
    #include <unistd.h>
    #include <time.h>
    #include <utils/threads.h>
    
    // # of milliseconds to fudge stopwatch measurements
    #define TIMING_TOLERANCE_MS 25
    
    using namespace android;
    using namespace std;
    
    class StubMessageHandler : public MessageHandler {
    public:
        Vector<Message> messages;
    
        virtual void handleMessage(const Message& message) {
            ALOGD("[Thread=%d] %s message.what=%d 
    ", gettid(), __func__, message.what);
            messages.push(message);
        }
    };
    
    struct LooperThread : public Thread {
    public:
        LooperThread(Looper *looper)
            : mLooper(looper) {
        }
    
        virtual bool threadLoop() {
            if(mLooper == NULL)
                return false;
            int32_t ret = mLooper->pollOnce(-1);
            switch (ret) {
                case Looper::POLL_WAKE:
                case Looper::POLL_CALLBACK:
                    return true;
                case Looper::POLL_ERROR:
                    ALOGE("Looper::POLL_ERROR");
                    return true;
                case Looper::POLL_TIMEOUT:
                    // timeout (should not happen)
                    return true;
                default:
                    // should not happen
                    ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                    return true;
            }
        }
    
    protected:
        virtual ~LooperThread() {}
    
    private:
        Looper *mLooper;
    };
    
    
    class CallbackHandler {
    public:
        CallbackHandler() : callbackCount(0) {}
        void setCallback(const sp<Looper>& looper, int fd, int events) {
            looper->addFd(fd, 0, events, staticHandler, this);
        }
    
    protected:
        int handler(int fd, int events) {
            callbackCount++;
            ALOGD("[Thread=%d] %s fd=%d, events=%d, callbackCount=%d
    ", gettid(), __func__, fd, events, callbackCount);
            return 0;
        }
    
    private:
        static int staticHandler(int fd, int events, void* data) {
            return static_cast<CallbackHandler*>(data)->handler(fd, events);
        }
        int callbackCount;
    };
    
    
    class Pipe {
    public:
        int sendFd;
        int receiveFd;
    
        Pipe() {
            int fds[2];
            ::pipe(fds);
    
            receiveFd = fds[0];
            sendFd = fds[1];
        }
    
        ~Pipe() {
            if (sendFd != -1) {
                ::close(sendFd);
            }
    
            if (receiveFd != -1) {
                ::close(receiveFd);
            }
        }
    
        status_t writeSignal() {
            ssize_t nWritten = ::write(sendFd, "*", 1);
            return nWritten == 1 ? 0 : -errno;
        }
    
        status_t readSignal() {
            char buf[1];
            ssize_t nRead = ::read(receiveFd, buf, 1);
            return nRead == 1 ? 0 : nRead == 0 ? -EPIPE : -errno;
        }
    };
    
    int main(int argc, char ** argv)
    {
        // Looper的轮询处理工作在新线程中
        sp<Looper> mLooper = new Looper(true);
        sp<LooperThread> mLooperThread = new LooperThread(mLooper.get());
        mLooperThread->run("LooperThread");
    
        // 测试消息的发送与处理
        sp<StubMessageHandler> handler = new StubMessageHandler();
        ALOGD("[Thread=%d] sendMessage message.what=%d 
    ", gettid(), 1);
        mLooper->sendMessage(handler, Message(1));
        ALOGD("[Thread=%d] sendMessage message.what=%d 
    ", gettid(), 2);
        mLooper->sendMessage(handler, Message(2));
        
        sleep(1);
        
        // 测试监测fd与回调callback
        Pipe pipe;
        CallbackHandler mCallbackHandler;
        mCallbackHandler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
        ALOGD("[Thread=%d] writeSignal 1
    ", gettid());
        pipe.writeSignal(); // would cause FD to be considered signalled
        sleep(1);
        mCallbackHandler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
        ALOGD("[Thread=%d] writeSignal 2
    ", gettid());
        pipe.writeSignal();
        
        sleep(1);
        mLooperThread->requestExit();
        mLooper.clear();
    }
    View Code

    编译Android.mk,如下

    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES := LooperTest.cpp
    
    LOCAL_SHARED_LIBRARIES := 
                           liblog 
                           libutils 
    
    LOCAL_C_INCLUDES := 
                     system/core/include/cutils 
    
    LOCAL_MODULE_TAGS := optional
    
    LOCAL_MODULE := LooperTest
    
    include $(BUILD_EXECUTABLE)
    View Code

    运行

    • 将上面的源代码及makefile文件放到android源码环境下,执行mm编译,得到可执行档LooperTest,将其push到测试机/system/bin/LooperTest,执行 LooperTest即可
    • 可以使用 logcat -s LooperTest 抓取log查看运行情况

    分析

    • StubMessageHandler : 定义消息处理程序,继承自MessageHandler,实现其中的handleMessage以处理消息
    • LooperThread:定义Looper运行的线程,在单独的子线程中不断调用pollOnce来处理消息或回调
    • CallbackHandler:定义fd事件的回调处理程序,其中实现typedef int (Looper_callbackFunc)(int fd, int events, void* data);类型的回调函数

    核心处理就是如下过程:

    1. 创建Looper实例,并开启一个新线程来调用poolOnce

    // Looper的轮询处理工作在新线程中
    sp<Looper> mLooper = new Looper(true);
    sp<LooperThread> mLooperThread = new LooperThread(mLooper.get());
    mLooperThread->run("LooperThread");
    View Code

    2. 创建消息并指定Handler,调用sendMessage发送给Looper

    // 测试消息的发送与处理
    sp<StubMessageHandler> handler = new StubMessageHandler();
    ALOGD("[Thread=%d] sendMessage message.what=%d 
    ", gettid(), 1);
    mLooper->sendMessage(handler, Message(1));
    View Code

    3. 添加监测的fd并设置回调函数

    Pipe pipe;
    CallbackHandler mCallbackHandler;
    mCallbackHandler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
    ALOGD("[Thread=%d] writeSignal 1
    ", gettid());
    pipe.writeSignal(); // would cause FD to be considered signalled
    View Code

    4. 新线程来调用poolOnce会阻塞在epoll_wait,当收到新Message或fd events 就会唤醒,调用对应的handleMessage或callback

    结语

    通过上面两篇文章的学习,基本把Looper的原理及使用讲清楚了,当然受限于本人能力,可能有错误之处。

     

    心有猛虎,细嗅蔷薇,生活就该无惧无悔..... PS:文章系作者工作学习总结,受作者知识水平的限制,文章难免有错误之处,仅供参考,转载请注明出处:http://www.cnblogs.com/roger-yu/
  • 相关阅读:
    当import的模块内容发生变化时,对此模块进行重新加载(刷新)
    使用python的ctypes库实现内存的动态申请和释放
    【转载】实现博客园图片的可放大功能
    使用tqdm实现下载文件进度条
    pytest参数化的两种方式
    Jmeter之Bean shell使用-常用内置变量
    JMeter之Ramp-up Period(in seconds)说明
    Jmeter性能测试基础
    接口测试基础
    JMeter做http接口功能测试
  • 原文地址:https://www.cnblogs.com/roger-yu/p/15100416.html
Copyright © 2011-2022 走看看