Flutter事件模型(基于Android)

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

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

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

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

现在回到./fml/thread.cc

Thread::Thread(cost std::string& name) : joined_(false){
  fml::AutoResetWaitableEvent latch;
  fml::RefPtr runner;
  thread = std::make_unique()[&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 loop_;
    fml::RefPtr task_runner_;
} 

//message_loop_impl.h
class MessageLoopImpl : public Weakable {
  private:
    fml::RefPtr task_queue_;
    TaskQueueId queue_id_;
} 

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

//message_loop.cc
FML_THREAD_LOCAL ThreadLocalUniquePtr 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(loop_)){
}

//message_loop_impl.cc
fml::RefPtr MessageLoopImpl::Create(){
#if OS_MACOSX
  return fml::MakeRefCounted();
#elif OS_ANDROID
  return fml::MakeRefCounted();
#elif OS_LINUX
  return fml::MakeRefCounted();
#elif OS_WIN
  return fml::MakeRefCounted();
#else
  return nullptr;
#endif
}
  • loop_
    因为我们讨论的是Android平台,因此这边MessageLoop中的loop_编程为MessageLoopAndroid对象。
//message_loop_android.h
class MessageLoopAndroid: public MessageLoopImpl {
  private:
    fml::UniqueObject 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(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::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::prepare(int opts){
  bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NOW_CALLBACKS;
  sp 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)->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 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> queue_entries_;
}

class TaskQueueEntry{
  public:
    using TaskObservers = std::map;
    Wakeable* wakeable;
    TaskObsevers task_observers;
    //从后面可以看到,是一个元素为DelayedTask的优先队列
    DelayedTaskQueue delayed_tasks;    
}

//delayed_task.h
class DelayedTask{
  private:
    fml::closure task_;
}

using DelayedTaskQueue = std::priotiry_queue,std::greater>;

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

//messahe_loop_task_queue.cc
fml::RefPtr MessageLoopTaskQueues::GetInstance(){
  //可以看到,MessageLoopTaskQueues是全局单例
  std::scoped_lock creation(creation_mutex_);
  if(!instance_){
    instance_=fml::MakeRefCounted();
  }
  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();
  queue_locks_[loop_id]=std::make_unique();
  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 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 observers = task_queue_->GetObserverToNotify(queue_id_);
    for(const auto& observer : observers){
      observer();
    }
  }
}

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

你可能感兴趣的:(Flutter事件模型(基于Android))