深入理解Flutter消息機制

Posted by Gityuan on July 20, 2019

基于Flutter 1.5,從源碼視角來深入剖析flutter消息處理機制,相關源碼目錄見文末附錄

一、概述

深入理解Flutter引擎啟動 已經介紹了引擎啟動階段會創建AndroidShellHolder對象,在該過程會執行ThreadHost初始化,MessageLoop便是在這個階段啟動的。

1.1 消息流程圖

MessageLoop啟動流程圖

MessageLoop_create

該過程主要工作:創建線程,并給每個線程中創建相應的MessageLoop,對于Android平臺創建的是MessageLoopAndroid,同時還會創建TaskRunner,之后便進入到相應MessageLoop的run()方法。

ScheduleMicrotask流程圖

ScheduleMicrotask

1.2 MessageLoop類圖

MessageLoop類圖

MessageModel

圖解:

  • Thread和MessageLoop類都有成員變量記錄著TaskRunner類;
  • MessageLoopImpl類在Android系統的實現子類為MessageLoopAndroid;

二、MessageLoop啟動

引擎啟動過程會創建UI/GPU/IO這3個線程,代碼如下。

thread_host_ = {thread_label, ThreadHost::Type::UI
                              | ThreadHost::Type::GPU
                              | ThreadHost::Type::IO};

2.1 ThreadHost初始化

[-> flutter/shell/common/thread_host.cc]

ThreadHost::ThreadHost(std::string name_prefix, uint64_t mask) {
  if (mask & ThreadHost::Type::Platform) {
    platform_thread = std::make_unique<fml::Thread>(name_prefix + ".platform");
  }

  if (mask & ThreadHost::Type::UI) {
    //創建線程 [見小節2.2]
    ui_thread = std::make_unique<fml::Thread>(name_prefix + ".ui");
  }

  if (mask & ThreadHost::Type::GPU) {
    gpu_thread = std::make_unique<fml::Thread>(name_prefix + ".gpu");
  }

  if (mask & ThreadHost::Type::IO) {
    io_thread = std::make_unique<fml::Thread>(name_prefix + ".io");
  }
}

根據傳遞的參數,可知首次創建AndroidShellHolder實例的過程,會創建3個線程名為1.ui, 1.gpu, 1.io。

2.2 Thread初始化

[-> flutter/fml/thread.cc]

Thread::Thread(const 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); //設置線程名
    fml::MessageLoop::EnsureInitializedForCurrentThread(); //[見小節2.3]
    //從ThreadLocal中獲取MessageLoop指針
    auto& loop = MessageLoop::GetCurrent();
    runner = loop.GetTaskRunner();
    latch.Signal();
    loop.Run(); //運行 [見小節2.8]
  });
  latch.Wait();
  task_runner_ = runner;
}

Thread線程對象會有兩個重要的成員變量:

  • thread_: 類型為unique_ptr
  • task_runner_: 類型為RefPtr

2.3 EnsureInitializedForCurrentThread

[-> flutter/fml/message_loop.cc]

FML_THREAD_LOCAL ThreadLocal tls_message_loop([](intptr_t value) {
  delete reinterpret_cast<MessageLoop*>(value);
});

void MessageLoop::EnsureInitializedForCurrentThread() {
  if (tls_message_loop.Get() != 0) {
    return;  //保證只初始化一次
  }
  //創建MessageLoop,并保持在tls_message_loop [見小節2.4]
  tls_message_loop.Set(reinterpret_cast<intptr_t>(new MessageLoop()));
}

創建MessageLoop對象保存在ThreadLocal類型的tls_message_loop變量中。

2.4 MessageLoop初始化

[-> flutter/fml/message_loop.cc]

MessageLoop::MessageLoop()
       //[見小節2.5]
    : loop_(MessageLoopImpl::Create()),
      //[見小節2.7]
      task_runner_(fml::MakeRefCounted<fml::TaskRunner>(loop_)) {
}

創建MessageLoopAndroid對象和TaskRunner對象,并保持在當前的MessageLoop對象的成員變量。

2.5 MessageLoopImpl::Create

[-> flutter/fml/message_loop_impl.cc]

fml::RefPtr<MessageLoopImpl> MessageLoopImpl::Create() {
#if OS_MACOSX
  return fml::MakeRefCounted<MessageLoopDarwin>();
#elif OS_ANDROID
  return fml::MakeRefCounted<MessageLoopAndroid>(); //[見小節2.6]
#elif OS_LINUX
  return fml::MakeRefCounted<MessageLoopLinux>();
#elif OS_WIN
  return fml::MakeRefCounted<MessageLoopWin>();
#else
  return nullptr;
#endif
}

針對Android平臺,則MessageLoopImpl的實例為MessageLoopAndroid對象。

2.6 MessageLoopAndroid初始化

[-> flutter/fml/platform/android/message_loop_android.cc]

MessageLoopAndroid::MessageLoopAndroid()
    : looper_(AcquireLooperForThread()), //[見小節2.6.1]
      timer_fd_(::timerfd_create(kClockType, TFD_NONBLOCK | TFD_CLOEXEC)),
      running_(false) {
  static const int kWakeEvents = 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(),          // looper
                                   timer_fd_.get(),        // fd
                                   ALOOPER_POLL_CALLBACK,  // ident
                                   kWakeEvents,            // events
                                   read_event_fd,          // callback
                                   this                    // baton
  );
}

2.6.1 AcquireLooperForThread

[-> flutter/fml/platform/android/message_loop_android.cc]

static ALooper* AcquireLooperForThread() {
  ALooper* looper = ALooper_forThread();

  if (looper == nullptr) {
    // 當前線程沒有配置looper,則創建一個loop
    looper = ALooper_prepare(0);
  }

  // 該線程已經有looper,則獲取該loop的引用
  ALooper_acquire(looper);
  return looper;
}

此處是通過android中的ndk工具實現loop消息機制。

2.6.2 timerfd_create

[-> flutter/fml/platform/linux/timerfd.cc]

int timerfd_create(int clockid, int flags) {
  return syscall(__NR_timerfd_create, clockid, flags);
}

通過系統調用來創建timerfd

2.7 TaskRunner初始化

[-> flutter/fml/task_runner.cc]

TaskRunner::TaskRunner(fml::RefPtr<MessageLoopImpl> loop)
    : loop_(std::move(loop)) {}

執行到這里,便完成了MessageLoop的初始化,回到小節2.2,接下來執行Run()方法。

2.8 MessageLoopAndroid::Run

[-> flutter/fml/platform/android/message_loop_android.cc]

void MessageLoopAndroid::Run() {
  running_ = true;

  while (running_) {
    int result = ::ALooper_pollOnce(-1,       // infinite timeout
                                    nullptr,  // out fd,
                                    nullptr,  // out events,
                                    nullptr   // out data
    );
    if (result == ALOOPER_POLL_TIMEOUT || result == ALOOPER_POLL_ERROR) {
      // 處理使用ALooper API終止循環的情況
      running_ = false;
    }
  }
}

該線程處于pollOnce輪詢等待的狀態。

三、生產Dart層Microtask

對于Dart框架層可調用scheduleMicrotask()方法是用于向Microtask Queue中添加task,接著從該方法說起。

3.1 scheduleMicrotask

[-> third_party/dart/sdk/lib/async/schedule_microtask.dart]

void scheduleMicrotask(void callback()) {
  _Zone currentZone = Zone.current;
  if (identical(_rootZone, currentZone)) {
    //rootZone [見小節3.2]
    _rootScheduleMicrotask(null, null, _rootZone, callback);
    return;
  }
  _ZoneFunction implementation = currentZone._scheduleMicrotask;
  if (identical(_rootZone, implementation.zone) &&
      _rootZone.inSameErrorZone(currentZone)) {
    _rootScheduleMicrotask(
        null, null, currentZone, currentZone.registerCallback(callback));
    return;
  }
  Zone.current.scheduleMicrotask(Zone.current.bindCallbackGuarded(callback));
}

此處以rootZone為例來展開說明

3.2 _rootScheduleMicrotask

[-> third_party/dart/sdk/lib/async/zone.dart]

void _rootScheduleMicrotask(
    Zone self, ZoneDelegate parent, Zone zone, void f()) {
  if (!identical(_rootZone, zone)) {
    bool hasErrorHandler = !_rootZone.inSameErrorZone(zone);
    if (hasErrorHandler) {
      f = zone.bindCallbackGuarded(f);
    } else {
      f = zone.bindCallback(f);
    }
    zone = _rootZone;
  }
  _scheduleAsyncCallback(f); // [見小節3.3]
}

3.3 _scheduleAsyncCallback

[-> third_party/dart/sdk/lib/async/schedule_microtask.dart]

void _scheduleAsyncCallback(_AsyncCallback callback) {
  _AsyncCallbackEntry newEntry = new _AsyncCallbackEntry(callback);
  if (_nextCallback == null) {
    //當鏈表為空,則設置當前回調Entry為鏈表的頭部
    _nextCallback = _lastCallback = newEntry;
    if (!_isInCallbackLoop) {
      // [見小節3.4]
      _AsyncRun._scheduleImmediate(_startMicrotaskLoop);
    }
  } else {
    //當鏈表不為空,則插入鏈表的尾部
    _lastCallback.next = newEntry;
    _lastCallback = newEntry;
  }
}

class _AsyncRun {
  //[見小節3.3.1]
  external static void _scheduleImmediate(void callback());
}

采用一個單向鏈表來記錄callback回調實體,其中_nextCallback是鏈表頭部,_lastCallback是鏈表尾部;此處的_scheduleImmediate最終會調用到dart runtime中的schedule_microtask_patch.dart文件。

3.4 _scheduleImmediate

[-> third_party/dart/runtime/lib/schedule_microtask_patch.dart]

class _AsyncRun {
  static void _scheduleImmediate(void callback()) {
    _ScheduleImmediate._closure(callback); //[見小節3.4.1]
  }
}

typedef void _ScheduleImmediateClosure(void callback());

class _ScheduleImmediate {
  static _ScheduleImmediateClosure _closure;
}

對于_ScheduleImmediate._closure的賦值過程,是在引擎啟動的過程。

3.4.1 InitDartAsync

在引擎啟動過程會創建RootIsolate,有如下調用鏈:

DartIsolate::CreateRootIsolate
  DartIsolate::CreateDartVMAndEmbedderObjectPair
    DartIsolate::LoadLibraries
      DartRuntimeHooks::Install
        flutter::InitDartAsync

再來看看InitDartAsync的實現過程,如下所示。

[-> flutter/lib/ui/dart_runtime_hooks.cc]

static void InitDartAsync(Dart_Handle builtin_library, bool is_ui_isolate) {
  Dart_Handle schedule_microtask;
  if (is_ui_isolate) {
    schedule_microtask = GetFunction(builtin_library, "_getScheduleMicrotaskClosure");
  } else {
    ...
  }
  Dart_Handle async_library = Dart_LookupLibrary(ToDart("dart:async"));
  Dart_Handle set_schedule_microtask = ToDart("_setScheduleImmediateClosure");
  Dart_Handle result = Dart_Invoke(async_library, set_schedule_microtask, 1,
                                   &schedule_microtask);
  PropagateIfError(result);
}

可見此處會調用schedule_microtask_patch.dart的_setScheduleImmediateClosure()。

@pragma("vm:entry-point", "call")
void _setScheduleImmediateClosure(_ScheduleImmediateClosure closure) {
  _ScheduleImmediate._closure = closure;
}

可見,經過InitDartAsync()方法,將_getScheduleMicrotaskClosure賦值給_closure。那么前面小節[3.3.1]便開始執行_getScheduleMicrotaskClosure()方法。

3.4.2 _getScheduleMicrotaskClosure

[-> flutter/lib/ui/natives.dart]

@pragma('vm:entry-point')
Function _getScheduleMicrotaskClosure() => _scheduleMicrotask;

void _scheduleMicrotask(void callback()) native 'ScheduleMicrotask'; //[見小節3.5]

3.5 ScheduleMicrotask

[-> flutter/lib/ui/dart_runtime_hooks.cc]

void ScheduleMicrotask(Dart_NativeArguments args) {
  Dart_Handle closure = Dart_GetNativeArgument(args, 0);
  UIDartState::Current()->ScheduleMicrotask(closure); //[見小節3.6]
}

此處的參數closure便是[小節3.3]中的_startMicrotaskLoop。

3.6 UIDartState::ScheduleMicrotask

[-> flutter/lib/ui/ui_dart_state.cc]

void UIDartState::ScheduleMicrotask(Dart_Handle closure) {
  microtask_queue_.ScheduleMicrotask(closure); //[見小節3.7]
}

3.7 DartMicrotaskQueue::ScheduleMicrotask

[-> third_party/tonic/dart_microtask_queue.cc]

void DartMicrotaskQueue::ScheduleMicrotask(Dart_Handle callback) {
  queue_.emplace_back(DartState::Current(), callback);
}

queue_的類型為MicrotaskQueue,記錄著所有的DartState所對應的Dart_Handle回調方法的隊列。由前面可知,此處callback為_startMicrotaskLoop()方法。

對于Microtask任務:

  • UIDartState::ScheduleMicrotask會向隊列中添加Microtask任務,添加后并不會喚醒目標線程;
  • UIDartState::FlushMicrotasksNow則會一次性消費掉全部的Microtask微任務。

四、生產引擎層Task

在Flutter引擎層會看到有不少TaskRunner::PostTask()的使用地方,如下所示。

void Animator::RequestFrame(bool regenerate_layer_tree) {
  ...
  task_runners_.GetUITaskRunner()->PostTask([self = weak_factory_.GetWeakPtr(),
                                             frame_number = frame_number_]() {
    self->AwaitVSync();
  });
}

4.1 TaskRunner::PostTask

[-> flutter/fml/task_runner.cc]

void TaskRunner::PostTask(fml::closure task) {
  //[見小節4.2]
  loop_->PostTask(std::move(task), fml::TimePoint::Now());
}

void TaskRunner::PostTaskForTime(fml::closure task,
                                 fml::TimePoint target_time) {
  loop_->PostTask(std::move(task), target_time);
}

void TaskRunner::PostDelayedTask(fml::closure task, fml::TimeDelta delay) {
  loop_->PostTask(std::move(task), fml::TimePoint::Now() + delay);
}

方法說明;

  • PostTask:立刻執行的任務;
  • PostTaskForTime:指定時間來執行的任務;
  • PostDelayedTask:延遲一段時間來執行的任務;

4.2 MessageLoopImpl::PostTask

[-> flutter/fml/message_loop_impl.cc]

void MessageLoopImpl::PostTask(fml::closure task, fml::TimePoint target_time) {
  RegisterTask(task, target_time);
}

4.3 MessageLoopImpl::RegisterTask

[-> flutter/fml/message_loop_impl.cc]

void MessageLoopImpl::RegisterTask(fml::closure task,
                                   fml::TimePoint target_time) {
  if (terminated_) {  //消息loop已終止則結束執行
    return;
  }
  std::lock_guard<std::mutex> lock(delayed_tasks_mutex_);
  //將該任務放入delayed_tasks_隊列
  delayed_tasks_.push({++order_, std::move(task), target_time});
  //在指定的時間會喚醒delayed_tasks_所在的線程[見小節4.3.1]
  WakeUp(delayed_tasks_.top().target_time);
}

delayed_tasks_的數據類型為DelayedTaskQueue,也就是std::priority_queue<DelayedTask, std::deque, DelayedTaskCompare>,該隊列是按照執行時間的前后順序來加入隊列的,當執行時間相同則按先后順序來執行。

struct DelayedTaskCompare {
  bool operator()(const DelayedTask& a, const DelayedTask& b) {
    return a.target_time == b.target_time ? a.order > b.order
                                          : a.target_time > b.target_time;
  }
};

4.3.1 WakeUp

[-> flutter/fml/platform/android/message_loop_android.cc]

void MessageLoopAndroid::WakeUp(fml::TimePoint time_point) {
  bool result = TimerRearm(timer_fd_.get(), time_point); //[見小節4.3.2]
}

每次向延遲任務隊列放入消息的同時,會設置目標時間來喚醒的操作。

4.3.2 TimerRearm

[-> flutter/fml/platform/linux/timerfd.cc]

bool TimerRearm(int fd, fml::TimePoint time_point) {
  const uint64_t nano_secs = time_point.ToEpochDelta().ToNanoseconds();

  struct itimerspec spec = {};
  spec.it_value.tv_sec = (time_t)(nano_secs / NSEC_PER_SEC);
  spec.it_value.tv_nsec = nano_secs % NSEC_PER_SEC;
  spec.it_interval = spec.it_value;
  //設置定時喚醒
  int result = ::timerfd_settime(fd, TFD_TIMER_ABSTIME, &spec, nullptr);
  return result == 0;
}

通過系統調用__NR_timerfd_settime來設置定時喚醒。

五、消費任務

任務消費有兩個時機:

  • 幀開始繪制過程Window::BeginFrame(),會調用UIDartState::FlushMicrotasksNow()會消費Microtask;
  • MessageLoop的消息循環過程,會同時消費Microtask和引擎層Task;

5.1 添加TaskObserver

5.1.1 UIDartState初始化

[-> flutter/lib/ui/ui_dart_state.cc]

UIDartState::UIDartState(...) {
  //UIDartState對象創建時添加task observer [見小節5.1.2]
  AddOrRemoveTaskObserver(true);
}

UIDartState::~UIDartState() {
  //UIDartState對象銷毀時移除task observer
  AddOrRemoveTaskObserver(false ;
}

5.1.2 AddOrRemoveTaskObserver

[-> flutter/lib/ui/ui_dart_state.cc]

void UIDartState::AddOrRemoveTaskObserver(bool add) {
  auto task_runner = task_runners_.GetUITaskRunner();
  ...
  if (add) {
    //[見小節5.1.4]
    add_callback_(reinterpret_cast<intptr_t>(this),
                  [this]() { this->FlushMicrotasksNow(); });
  } else {
    remove_callback_(reinterpret_cast<intptr_t>(this));
  }
}

引擎啟動的DartIsolate初始化時,會創建一個UIDartState對象,則向MessageLoop中添加一個TaskObserver,其中以當前UIDartState對象為key,以FlushMicrotasksNow()方法為value;當UIDartState對象銷毀時移除task observer。 再來看看add_callback_的賦值過程,如下所示。

5.1.3 FlutterMain::Init

在Flutter引擎啟動時執行FlutterActivity的onCreate()過程,會調用FlutterMain::Init()方法

[-> flutter/shell/platform/android/flutter_main.cc]

void FlutterMain::Init(...) {
  ...
  //初始化observer的增加和刪除方法
  settings.task_observer_add = [](intptr_t key, fml::closure callback) {
    fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
  };

  settings.task_observer_remove = [](intptr_t key) {
    fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
  };
}

可見,settings的task_observer_add和task_observer_remove分別對應消息循環中的增加和移除TaskObserver的功能。

DartIsolate::DartIsolate(const Settings& settings, ...)
    : UIDartState(std::move(task_runners),
                  settings.task_observer_add,
                  settings.task_observer_remove, ...),
      ...) {
}

而在DartIsolate對象初始化過程,會將settings的這兩個方法賦值其成員變量add_callback_和remove_callback_。 可見,add_callback_所對應的便是MessageLoopImpl::AddTaskObserver()方法,如下所示。

5.1.4 AddTaskObserver

[-> flutter/fml/message_loop_impl.cc]

void MessageLoopImpl::AddTaskObserver(intptr_t key, fml::closure callback) {
  task_observers_[key] = std::move(callback);
}

void MessageLoopImpl::RemoveTaskObserver(intptr_t key) {
  task_observers_.erase(key);
}

task_observers_是一個map類型,以UIDartState實例對象為key,以FlushMicrotasksNow()方法為value。

說明:AddTaskObserver()過程便是向task_observers_中添加相應UIDartState的FlushMicrotasksNow()方法,用于在MessageLoop過程來消費Microtask。

5.2 FlushTasks

[-> flutter/fml/message_loop_impl.cc]

void MessageLoopImpl::FlushTasks(FlushType type) {
  TRACE_EVENT0("fml", "MessageLoop::FlushTasks");
  std::vector<fml::closure> invocations;

  {
    std::lock_guard<std::mutex> lock(delayed_tasks_mutex_);
    if (delayed_tasks_.empty()) {
      return;
    }

    auto now = fml::TimePoint::Now();
    //遍歷整個延遲任務隊列,將時間已到期的任務加入invocations
    while (!delayed_tasks_.empty()) {
      const auto& top = delayed_tasks_.top();
      if (top.target_time > now) {
        break;
      }
      invocations.emplace_back(std::move(top.task));
      delayed_tasks_.pop();
      if (type == FlushType::kSingle) {
        break;
      }
    }
    //喚醒延遲隊列所在線程
    WakeUp(delayed_tasks_.empty() ? fml::TimePoint::Max()
                                  : delayed_tasks_.top().target_time);
  }
  //開始執行真正的遍歷
  for (const auto& invocation : invocations) {
    invocation(); //執行已到期的任務
    for (const auto& observer : task_observers_) {
      observer.second(); //執行微任務 [見小節5.3]
    }
  }
}

該方法說明:

  • 遍歷整個延遲任務隊列,將時間已到期的任務加入invocations隊列
  • 依次執行所有的任務
  • 遍歷執行所有的微任務,通前面小節[5.1]可知,此處observer.second()代表的是FlushMicrotasksNow()方法

5.3 FlushMicrotasksNow

[-> flutter/lib/ui/ui_dart_state.cc]

void UIDartState::FlushMicrotasksNow() {
  microtask_queue_.RunMicrotasks(); //[見小節5.4]
}

5.4 RunMicrotasks

[-> third_party/tonic/dart_microtask_queue.cc]

void DartMicrotaskQueue::RunMicrotasks() {
  while (!queue_.empty()) {
    MicrotaskQueue local;
    std::swap(queue_, local);
    for (const auto& callback : local) {
      if (auto dart_state = callback.dart_state().lock()) {
        DartState::Scope dart_scope(dart_state.get());
        //執行正在的回調方法
        Dart_Handle result = Dart_InvokeClosure(callback.value(), 0, nullptr);
        ... //異常處理
        dart_state->MessageEpilogue(result);
        if (!Dart_CurrentIsolate())
            return;
      }
    }
  }
}

從前面小節[3.7]可知,此處callback.value便是_startMicrotaskLoop(),接下來回調到dart層。

5.5 _startMicrotaskLoop

[-> third_party/dart/sdk/lib/async/schedule_microtask.dart]

void _startMicrotaskLoop() {
  _isInCallbackLoop = true;
  try {
    _microtaskLoop();
  } finally {
    _lastPriorityCallback = null;
    _isInCallbackLoop = false;
    if (_nextCallback != null) {
      //當前面遍歷,當鏈表不為空,則繼續調度下一個微任務 [見小節3.4]
      _AsyncRun._scheduleImmediate(_startMicrotaskLoop);
    }
  }
}

5.6 _microtaskLoop

[-> third_party/dart/sdk/lib/async/schedule_microtask.dart]

void _microtaskLoop() {
  //遍歷執行所有的微任務
  while (_nextCallback != null) {
    _lastPriorityCallback = null;
    _AsyncCallbackEntry entry = _nextCallback;
    _nextCallback = entry.next;
    if (_nextCallback == null) _lastCallback = null;
    (entry.callback)();  //執行微任務的回調方法
  }
}

此處的callback便是前面生產MicroTask過程的小節[3.1]scheduleMicrotask()方法的參數callback。

六、總結

Flutter引擎啟動過程,會創建UI/GPU/IO這3個線程,并且會為每個線程依次創建MessageLoop對象,啟動后處于epoll_wait等待狀態。對于Flutter的消息機制跟Android原生的消息機制有很多相似之處,都有消息(或者任務)、消息隊列以及Looper,有一點不同的是Android有一個Handler類,用于發送消息以及執行回調方法,相對應Flutter中有著相近功能的便是TaskRunner。

消息機制采用的是生產者-消費者模型,本文介紹了兩類任務:引擎層的Task和Dart層的Microtask,當然還有Future和DartVM中的消息處理,會在下一篇文章講解。

  • C++引擎層的Task
    • MessageLoopImpl::RegisterTask():生產Task
    • MessageLoopImpl::FlushTasks():消費Task
  • Dart層的Microtask
    • scheduleMicrotask():生成Microtask
    • Window::BeginFrame():消費Microtask
    • MessageLoopImpl::FlushTasks():消費Microtask

在引擎中每次消費任務時調用FlushTasks()方法,遍歷整個延遲任務隊列delayed_tasks_,將時間已到期的任務加入invocations,緊接著會遍歷執行FlushMicrotasksNow()來消費所有的微任務。

附錄

本文涉及到相關源碼文件

flutter/shell/common/thread_host.cc
flutter/shell/platform/android/flutter_main.cc

flutter/fml/
  - thread.cc
  - task_runner.cc
  - message_loop.cc
  - message_loop_impl.cc
  - platform/android/message_loop_android.cc
  - platform/linux/timerfd.cc


flutter/lib/ui/
  - dart_runtime_hooks.cc
  - natives.dart
  - ui_dart_state.cc

third_party/dart/sdk/lib/async/schedule_microtask.dart
third_party/dart/sdk/lib/async/zone.dart
third_party/dart/runtime/lib/schedule_microtask_patch.dart
third_party/tonic/dart_microtask_queue.cc

微信公眾號 Gityuan | 微博 weibo.com/gityuan | 博客 留言區交流
万人炸金花官网