栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > C/C++/C#

Android native层Hander原理分析

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android native层Hander原理分析

目录

概述

自实现

下面简单叙述其原理:

如何使用:

注意问题:


概述

本篇探究 Android framework native层多媒体库中的 AHandler+ALooper+AMessage 这三个类的关系和机制,并借鉴此原理,用c++(c++17)重新实现自己的Handler+Looper+Message.  实现可以支持异步和同步的消息处理结构。

android里面的这三个类 在  /frameworks/av/media/libstagefright/foundation
可以在如下 在线 aosp源码找到 http://www.aospxref.com/android-12.0.0_r3/xref/frameworks/av/media/libstagefright/foundation/
android中取名在前面加了个前缀 A, 表示android.  

自实现


基于此重新用c++写的 CHandler CLooper CMessage ,在个人的github:https://github.com/Canok7/openScreen/commit/74ae413b916d66a87f27f9c614ab2b2f26104635

下面简单叙述其原理:

looper 为主循环,内部存在一个消息链表,存储着这个消息和该消息应该被处理的时间点,该链表插入消息的时候有序插入,是确保消息是按照消息的处理时间的先后来进行排序的,循环体不停地从链表中取出最先需要处理的消息,如果没有消息,进入条件等待,如果有就调用消息的所绑定的目标hander的onMessageReceived函数。 所以核心即按执行时间排序的消息链表和线程条件等待机制。

 

 

如何使用:

1. 建一个looper 调用start()   。也可以给looper设置线程名称,方便调试

 std::shared_ptr mSink_Loop = std::make_shared();
 mSink_Loop->setName("test_looper");
 mSink_Loop->start();

2. 建一个自定义的Handler,将其注册到looper .(注册到looper有两个作用,一是绑定looper和hander的对应关系,后续Message即可通过handler来找到looper,二是要确保一个hander只能被注册一次,不能绑定到多个looper上去,所以源码里面有LooperRoster,它用一张map表记录有所有的handler和looper对应关系。 这个对象是全局唯一的,即一个进程中只有一个LooperRoster)

class LooperTest : public CHandler{
public:
    enum{
        MSG_SAY,
        MSG_SUM,
    };
    LooperTest() = default;
    virtual ~LooperTest() = default;
    void onMessageReceived(const std::shared_ptr &msg) override{
        switch (msg->what()) {
            case MSG_SAY:
            {
                std::string say_Str;
                int32_t say_Int=0;
                CHECK(msg->findString("say_Str", &say_Str));
                CHECK(msg->findInt32("say_Int", &say_Int));
                ALOGD("[%s%d](%d) say_Str.c_str():%s,say_Int:%dn",__FUNCTION__,__LINE__,gettid(),say_Str.c_str(),say_Int);
            }
                break;
            case MSG_SUM:
            {
                //get reply from msg
                std::shared_ptr replyID;
                CHECK(msg->senderAwaitsResponse(&replyID));

                //do work
                int32_t add1=0,add2=0;
                msg->findInt32("add1", &add1);
                msg->findInt32("add2", &add2);
                ALOGD("[%s%d](%d) to sum:%d,%dn",__FUNCTION__,__LINE__,gettid(),add1,add2);

                //post resut
                std::shared_ptr response = std::make_shared();
                response->setInt32("result", add1+add2);
                response->postReply(replyID);
            }
                break;
            default:
                ALOGD("unKnow msg:%dn",msg->what());
                break;
        }
    }
};
enum{
    TEST_THREAD,
    TEST_SP,
    TEST_LOOPER,
    TEST_ABUFFER_LIST,
};

// 
 std::shared_ptr mHander = std::make_shared();
 mSink_Loop->registerHandler(mHander);

3. 建一个Message, 设定message 的Handler 和what.(可以直接在构造函数中携带)  调用异步处理post(只管把消息发出去,不管结果),或者同步postAndAwaitResponse(把消息发出去,并且阻塞在这里等待返回结果)
 

//异步
 std::shared_ptr msg = std::make_shared(LooperTest::MSG_SAY,mHander);
    msg->setString("say_Str", "hello");
    msg->setInt32("say_Int", count++);
    msg->post();

//同步等待
 std::shared_ptr msg = std::make_shared(LooperTest::MSG_SUM,mHander);
    msg->setInt32("add1", 7);
    msg->setInt32("add2", 8);
    ALOGD("[%s%d](%d) postAndAwaitResponsen",__FUNCTION__,__LINE__,gettid());
    std::shared_ptr response;
    //this will make a reply,and wait !!
    status_t err = msg->postAndAwaitResponse(&response);
    ALOGD("[%s%d] -----debug %d err ",__FUNCTION__ ,__LINE__,err);
    if (err == OK) {
        int ret=0;
        response->findInt32("result", &ret);
        ALOGD("[%s%d]xxxxxxxxxxxx(%d) get add ret:%dn",__FUNCTION__,__LINE__,gettid(),ret);
    }

注意问题:

        1. 为了保证所有的Handler只会被绑定到一个Looper, 这里有一个单例的LooperRoster . 调试的时候可以从LooperRoster中看到所有已注册的looper和Handler.  外部register的时候如果Handler已经被注册,register将不成功。
        2. Message持有Looper Handler ,  Handler持有Looper,  存储的都是weak_ptr,  如果某个Handler已经被释放,looper循环体在处理和这个Handler对应的消息时会忽略这个Message,不会发生错误。
        3. 调用者往Looper里面注册Handler, 相应地也应该需要调用反注册的机制,但是如果忘了没用调用反注册(registerHandler/unregisterHandler),也不会发生错误,在Looper的构造函数中会调用gLooperRoster.unregisterStaleHandlers()候判断哪一些handler已经是被析构了,然后去掉这些已经析构的无效Handler.

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1038824.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号