addTransientCallbacks method

void addTransientCallbacks()

首先,我希望所有的任务都在构建前进行统一处理, 1.所以要么在build中添加hook来拿到这个时间节点,而且在build中hook的方式必须触发build才行 2.要么就是在build之前,layout之后,同理可以在layout之后,或者paint过程中添加hook 3.要么就是添加到微任务队列中,没有任何hook的方式,如果在动画阶段,添加的话没有任何问题 如果在idle阶段,则添加的微任务会在build和layout之前触发,不满足需求

Implementation

void addTransientCallbacks() {
  mtLog("addTransientCallbacks");
  if (hasAddTransitentCallback) {
    return;
  }
  hasAddTransitentCallback = true;
  int beginFrame = FrameUtil.frameCount;
  // ignore: unused_local_variable
  final stackTrace = StackTrace.current;

  /// 如果由动画触发的添加任务,并且之后异步任务请求是同步完成的,那么就是transientCallbacks阶段
  /// transientCallbacks阶段添加transientCallback任务不会在当地立即触了,必须等到下一帧才行
  /// 因此会出现即使是同步任务,仍然非同帧加载
  final phase = FrameUtil.phase;
  WidgetsBinding.instance.scheduleFrameCallback((timeStamp) {
    mtLog("scheduleFrameCallback");
    int transitentFrame = FrameUtil.frameCount;
    Future.microtask(() {
      int micFrame = FrameUtil.frameCount;
      assert(() {
        if (beginFrame == transitentFrame && beginFrame == micFrame) {
          /// 只有最初的任务是build阶段触发,所以可能会出现微任务发生在下一帧
          /// 但是我们在添加任务的时候做一下处理即可。
          return true;
        } else {
          assert(phase == SchedulerPhase.transientCallbacks, "先不考虑mid微任务阶段");
          return true;
        }
        // return false;
      }(), "应该是完全一致的");
      // try {
      mtLog("微任务modifyDataAndCorrectPixelCallback处理之前", tag: TagsConfig.tagTestMicroQues);
      infiniteScorllController.modifyDataAndCorrectPixelCallback();
      mtLog("微任务modifyDataAndCorrectPixelCallback处理之后", tag: TagsConfig.tagTestMicroQues);

      // } catch (e) {
      //   /// TODO 如何比较好的处理进入时间循环的堆栈信息呢?
      //   mtLog("(((------");
      //   mtLog(e);
      //   debugPrintStack(stackTrace: stackTrace, maxFrames: 10, label: "未捕获到的错误");
      //   mtLog("------)))");
      //   assert(false);
      //   rethrow;
      // }
    });
  });
  WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
    hasAddTransitentCallback = false;
  });
}