Android Native -- Message/Handler/Looper机制(应用篇)


⌈Android Native消息队列处理系列文章⌋

Android Native -- Message/Handler/Looper机制(原理篇)

Android Native -- Message/Handler/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 \n", 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\n", 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 \n", gettid(), 1);
    mLooper->sendMessage(handler, Message(1));
    ALOGD("[Thread=%d] sendMessage message.what=%d \n", 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\n", 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\n", gettid());
    pipe.writeSignal();
    
    sleep(1);
    mLooperThread->requestExit();
    mLooper.clear();
}

编译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)

运行

  • 将上面的源代码及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");

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

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

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

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

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

 

结语

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

 

 

posted on 2021-08-04 19:19  二的次方  阅读(2268)  评论(2编辑  收藏  举报