美文网首页
Flutter事件模型(基于Android)

Flutter事件模型(基于Android)

作者: Wi1ls努力努力再努力 | 来源:发表于2020-10-22 10:28 被阅读0次

    在创建AndroidShellHolder的过程中,会通过ThreadHost创建UI、GPU、IO线程,这些线程属于fml:thread

    //./fml/thred.h
    class Thread{
      private:
        std::unique_ptr<std::thread> thread_;
        fml::RefPtr<fml::TaskRunner> task_runner_;
    }
    

    来看一个线程是如何创建的

    //thread_host.cc
    ui_thread = std::make_unique<fml::Thread>(name_prefix + ".ui);
    

    现在回到./fml/thread.cc

    Thread::Thread(cost std::string& name) : joined_(false){
      fml::AutoResetWaitableEvent latch;
      fml::RefPtr<fml::TaskRunner> runner;
      thread = std::make_unique<std::thread>()[&latch, &runner, name]() -> void {
        //设置线程名
        SetCurrentThreadName(name);
        //创建MessageLooper
        fml::MessageLoop::EnsureInitializedForCurrentThread();
        auto& loop = MessageLoop::GetCurrent();
        //runner赋值
        runner = loop.GetTaskRunner();
        latch.Singal();
        looper.Run();
      };  
      latch.Wait();
      task_runner_ = runner;
    }
    

    核心还是在MessageLooper的创建;
    先来看数据结构

    //message_loop.h
    class MessageLoop {
      private:
        fml::RefPtr<MessageLoopImpl> loop_;
        fml::RefPtr<fml::TaskRunner> task_runner_;
    } 
    
    //message_loop_impl.h
    class MessageLoopImpl : public Weakable {
      private:
        fml::RefPtr<MessageLooperTaskQueue> task_queue_;
        TaskQueueId queue_id_;
    } 
    

    看完了数据结构,可以找到MessageLoopImpl是作为成员变量在MessageLoop中提供,

    //message_loop.cc
    FML_THREAD_LOCAL ThreadLocalUniquePtr<MessageLoop> tls_message_loop;
    
    void MessageLoop::EnsureInitializedForCurrentThread(){
      //可以看到MessageLoop是ThreadLocal的
      if(tls_message_loop.get() != nullptr){
        return;
      }
      tls_message_loop.reset(new MessageLoop()); 
    }
    
    MessageLoop::MessageLoop()
      : loop_(MessageLoopImpl::Create()),
        task_runner_(fml::MakeRefCounted<fml::TaskRunner>(loop_)){
    }
    
    //message_loop_impl.cc
    fml::RefPtr<MessageLoopImpl> MessageLoopImpl::Create(){
    #if OS_MACOSX
      return fml::MakeRefCounted<MessageLoopDarwin>();
    #elif OS_ANDROID
      return fml::MakeRefCounted<MessageLoopAndroid>();
    #elif OS_LINUX
      return fml::MakeRefCounted<MessageLoopLinux>();
    #elif OS_WIN
      return fml::MakeRefCounted<MessageLoopWin>();
    #else
      return nullptr;
    #endif
    }
    
    • loop_
      因为我们讨论的是Android平台,因此这边MessageLoop中的loop_编程为MessageLoopAndroid对象。
    //message_loop_android.h
    class MessageLoopAndroid: public MessageLoopImpl {
      private:
        fml::UniqueObject<ALooper* UniqueLooperTraits> looper_;
        fml::UniqueFD timer_fd_;
    }
    //message_loop_android.cc
    MessageLoopAndroid::MessageLoopAndroid()
        : looper_(AcquireLooperForThread()),
          timer_fd(::timerfd_create(kClokType, TFD_NONBLOCK | TFD_CLOEXEC)){
      static const int kWakeEvent = ALOOPER_EVENT_INPUT;
      ALooper_callbackFunc read_event_fd = [](int,int events, void* data) -> int {
        if(events & kWakeEvents){
          reinterpret_Cast<MessageLoopAndroid*>(data)->OnEventFired();
        }
        return 1;
      }
      int add_result = ::ALooper_addFd(looper_.get(),                              //loop
                                                                timer_fd_.get(),                            //fd
                                                                ALOOPER_POLL_CALLBACK,    //ident
                                                                kWakeEvents,                              //event
                                                                read_event_fd,                            //callback
                                                                this);                                            //baton
    }
    
    static ALooper* AcquireLooperForThread(){
      ALooper* looper = ALooper_forThread();
      if(looper = nullptr){
        looper = ALooper_prepar(0);
      }
      ALooper_acquire(looper);
      rerturn looper;
    }
    

    这里有关键的几个点,首先通过AcquireLooperForThread()产生一个looper_对象,随后通过::timefd_create()创建一个timer_fd, 构造一个回调read_event_fd,将timer_fd添加到looper_,回调为read_event_fd,关键的事件是ALOOPER_EVENT_INPIT;这里要先熟悉Android中native端的looper机制才可以。

    以下代码是在android端源码framework中

    //./native/include/utils/Looper.h
    class Looper: public ALooper
    
    //./base/native/android/looper.cpp
    sp<Looper> Looper::getForThread(){
       //可以看到 looper是从ThreadLocal中获取的
      return (Looper*)pthread_getspecific(gTLSKey);
    }
    ALooper* ALooper_prepare(int opts){
      return Looper::prepare(opts).get();
    }
    
    //./native/libs/utils/Looper.cpp
    sp<Looper> Looper::prepare(int opts){
      bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NOW_CALLBACKS;
      sp<looper> looper = Looper::getForThread();
      if(looper == NULL){
        looper = new Looper(allowNonCallbacks);
        Looper::setFotThread(loop);
      }
      return looper;
    }
    

    关于native的Looper,看这一篇文章,
    至此,我们得知,MessageLoopImpl中有MessageLooperAndroid变量作为loop_,MessageLooperAndroid有一个Android端的Looper变量作为looper_;

    • timer_fd

    获得timer_fd的方式为

    static constexpr int kClockType = CLOCK_MONOTONIC;
    ::timerfd_create(kClockType, TFD_NONBLOCK | TFD_CLOEXEC);
    
    //./fml/platform/linux/timerfd.cc
    int timerfd_create(int clockid, int flags){
      return syscall(__NR_timerfd_create, clockid, flags);  
    }
    
    //framework/base/native/android/looper.cpp
    int ALooper+addFd(ALooper* looper, int fd, int ident, int events, ALooper_callbackFunc callback, void* data){
      retiurn static_cast<Looper*>(looper)->addFd(fd, ident, event, callback, data);
    }
    

    这里是利用Liunx的系统调用返回一个定时器的文件描述符,可以预料到,Flutter在android端是利用定时器(timer_fd)与原始looper的epoll机制(addFd()@looper)进行事件分发。##


    接下里还有一个关键的点,那就是MessageLoopImpl, MessageLoopAndroid派生自MessageLoopImpl

    //message_loop_impl.h
    class MessageLoopImpl : public Wakeable{
      private:
        flm::RefPtr<MessageLoopTaskQueue> task_queue_;
        TaskQueueId queue_id
    }
    //message_loop_impl.cc
    MessageLoopImpl::MessageLoopImpl()
        : task_queue_(MessageLoopTaskQueues::GetInstance()),
          queue_id(task_queue_->CreateTaskQueue()){
      task_queue_->SetWakeable(queue_id, this);
    }
    
    //message_loop+task_queue.h
    class MessageLoopTaskQueue{
      std::map<TaskQueueId, std::unique_ptr<TaskQueueEntry>> queue_entries_;
    }
    
    class TaskQueueEntry{
      public:
        using TaskObservers = std::map<intptr_t, fml::closure>;
        Wakeable* wakeable;
        TaskObsevers task_observers;
        //从后面可以看到,是一个元素为DelayedTask的优先队列
        DelayedTaskQueue delayed_tasks;    
    }
    
    //delayed_task.h
    class DelayedTask{
      private:
        fml::closure task_;
    }
    
    using DelayedTaskQueue = std::priotiry_queue<DelayedTask, std::deque<DelayedTask>,std::greater<DelayedTask>>;
    

    于是MessageLoopTaskQueue拥有一个键为TaskQueueId,值为TaskQueueEntry的Map,后者的核心是一个元素为DelayedTask的优先队列。

    //messahe_loop_task_queue.cc
    fml::RefPtr<MessageLoopTaskQueue> MessageLoopTaskQueues::GetInstance(){
      //可以看到,MessageLoopTaskQueues是全局单例
      std::scoped_lock creation(creation_mutex_);
      if(!instance_){
        instance_=fml::MakeRefCounted<MessageLoopTaskQueue>();
      }
      return isntance_();
    }
    
    TaskQueueId MessageLoopTaskQueues::CreateTaskQueue(){
      fml::UniqueueLock lock(*queue_meta_mutext_);
      TaskQueueId loop_id = TaskQueueId(task_queue_id_counter);
      ++task_queue_d_counter_;
      queue_entries_[loop_id] = std::make_unique<TaskQueueEntry>();
      queue_locks_[loop_id]=std::make_unique<std::mutex>();
      return loop_id;
    }
    

    可以看到,在MessageLoopTaskQueues中,创建的队列是以TaskQueueEntry的对象,以TaskQueueId最为key保存在map中的,因此可以将MessageLoopTaskQueues看为TaskQueueEntry的管理者。每一个MessageLoopImpl实际上是与自己的那个TaskQueueEntry进行打交道的。

    当我们想向某一个线程抛去一个任务时,一般是这样的

    thread_host.ui_thread->GetTaskRunner()->PostTask(jni_exit_task);
    
    //taskRunner.cc
    void TaskRUnner::PostTask(const fml::closure& task){
      loop_->PostTask(task, fml::TImePoint::Now());
    }
    //message_loop_impl.cc
    void MessageLoopImpl::PostTask(const flm::closure& task, fml::TimePoint target_time){
      task_queue->RegisterTask(queue_id_,task, target_time);
    }
    
    //message_loop_task_queue.cc
    void MessageLoopTaskQueues::RegisterTask(TaskQueueId queue_ud, const fml::closure& task,fml::TimePoint target_time){
      //获得自己关联的的TaskQueueEntry
      size_t order = order++;
      const auto& queue_entry = queue_entries_[queue_id];
      //往自己关联的DelayedTaskQueue队列推一个任务
      queue_entry->delayed_tasks.push({order, task, target_time});
      TaskQueueId loop_to_wake = queue_id;
      WakeUpUnlocked(loop_to_wake, queue_entry->delayed_tasks.top().getTargetTime());
    }
    void MessageLoopTaskQueues::WakeUpUnlocked(TaskQueueId queue_id, fml::TimePoint time) const {
      queue_entries_.at(queue_id)->wakeable->WakeUp(time);
    }
    

    细心的话,可以发现这里的wakeable就是MessageLoopImpl本身(构造函数赋值),在这里是MessageLoopAndroid

    //message_loop_android.cc
    void MessageLoopAndroid::WakeUp(fml::TimePoint time_point){
      bool result = TimerRearm(timer_fd_.get(),time_point);
    }
    
    //timerfd.cc
    bool TimerRearm(int fd, fml::TimePoint time_point){
      const uint64_t nano_secs = time_point.ToEpochDelta().ToNanoseconds();
      struct itimerspec spec = {};
      ...
      int result = ::timerfd_settime(fd, TFD_TIMER_ABSTIME, &spec, nullptr);
    }
    

    利用timerfd_settime来启动定时器,于是在指定时间后,timer_fd将会有事件可以读取,就会唤醒由于epoll机制阻塞的loop,就会发生OnEventFired()@MessageLoopAndroid的回调,###

    //message_loop_android.cc
    void MessageLoopAndroid::OnEventFired(){
      if(TimerDrain(timer_fd_.get())){
        RunExpiredTasksNow();
      }
    }
    //mesage_loop.cc
    void MessageLoop::RunExpiredTaskNow(){
      loop_->RunExpiredTaskNow();
    }
    //message_loop_impl.cc
    void MessageLoopImpl::RunExpiredTaskNow(){
      FlushTasks(FlushType::kAll);
    }
    void MessageLoopImpl::FlushTasks(FlushType type){
      std::vector<fml::closure> invocations;
      //这里就不分析,这里就是将符合本次执行的task放入invocations,然后根据不符合运行条件的第一个task或空的队列的目标时间再次设置进行唤醒。
      task_queue_->GetTaskToRunNow(queue_id_,type, invocations);
      for(const auto& invocation : invocations){
        invocation();
        //这里可以看到,observer是对task的一种监听,每有一个task完成,所有的observer都会被执行
        //从flutter的源码看的时候,可以看到对observers的注册
        std::Vector<fml::closure> observers = task_queue_->GetObserverToNotify(queue_id_);
        for(const auto& observer : observers){
          observer();
        }
      }
    }
    

    这么一个循环,Flutter Engine中的Android事件模型就摸清楚了,可以看到其他的平台如iOS,只是Looper的实现不一样,原理还是一样的利用定时器。

    相关文章

      网友评论

          本文标题:Flutter事件模型(基于Android)

          本文链接:https://www.haomeiwen.com/subject/jgpemktx.html