美文网首页IT之家Flutter知识
Keframe 分帧入屏: 处理flutter卡顿,优化流畅度

Keframe 分帧入屏: 处理flutter卡顿,优化流畅度

作者: 李小轰 | 来源:发表于2021-09-23 14:49 被阅读0次

    引言

    在掘金上浏览到Nayuta开源的贝壳flutter流畅优化组件 Keframe。在Demo上试用了一番,确有奇效,下面记录一下笔记心得。

    Keframe 处理思路

    • 卡顿的本质
      在一帧内,模块运行的时间太长,计算量太大

    Keframe 方案:分帧入屏 ,既然单帧的绘制时间太长,那我们就将一帧分成多帧。
    将屏幕上的 widget 扔进一个执行队列,将模块内的时间做拆分,多个 widget 不同时进行绘制,一个绘制完成后再进行下一个 widget 的绘制。

    Keframe 使用方法
    • 添加依赖(非空安全使用: 1.0.2; 空安全版本使用: 2.0.2)
    dependencies:
      keframe: version
    
    • 优化前的代码
    // CellWidget 是一个复杂的Item widget
    ListView.builder(
          itemCount: 100t,
          itemBuilder: (c, i) => CellWidget(),
        )
    
    • 使用Keframe 优化
    ListView.builder(
          itemCount: 100t,
          itemBuilder: (c, i) => FrameSeparateWidget(
              index: i,
              placeHolder: placeHolderWidget(),
              widget: CellWidget(),
          ),
        )
    

    FrameSeparateWidget: 分屏组件
    index: id标识,非必传,使用 SizeCacheWidget的场景必传
    placeHolder: 占位widget
    widget: 真实需要渲染的widget

    借用一下作者的图解:


    假如现在页面由 A、B、C、D 四部分组成,每部分耗时 10ms,在页面时构建为 40ms。使用分帧组件 FrameSeparateWidget 嵌套每一个部分。页面构建时会在第一帧渲染简单的占位,在后续四帧内分别渲染 A、B、C、D。

    另外 Keframe 还提供了一个工具类SizeCacheWidget用于缓存子节点中,分帧组件嵌套的实际 widget 的尺寸信息。对于列表,在每一个 item 中嵌套 FrameSeparateWidget,并将 ListView 嵌套在 SizeCacheWidget 内即可。

    SizeCacheWidget(
        child: ListView.builder(
         ...省略
        itemBuilder: (c, i) => FrameSeparateWidget(
        ...省略
        ),
        ),
    )
    
    SizeCacheWidget 的作用:

    当不确定实际 item 高度的时候,给 placeholder 设置一个近似的高度。并且在将 ListView 嵌套在 SizeCacheWidget 中。记录已渲染 widget 的大小尺寸,对于已渲染过的 widget 设置占位的尺寸。在滚动过程中,已经渲染过的 item 将不会出现跳动情况。


    原理分析

    • 分帧入屏


      FrameSeparateWidget
    • initState 初始化时 resultWidget 赋值为占位Widget
    • transformWidget initState和didUpdate都会触发,监听占位绘制完成,并将替换任务扔进分帧队列中
    FrameSeparateTaskQueue
    • await SchedulerBinding.instance!.endOfFrame : 如果当前正在绘制,等待当前帧结束。如果当前空闲,强制进行一帧的绘制,并等待结束。
    • await taskItemQueue.first.run() : 该方法为callback回调,真实内容就是替换占位widget
    • SizeCacheWidget
    //自定义冒泡通知
    class LayoutInfoNotification extends Notification {
      final Size size;
      final int? index;
      LayoutInfoNotification(this.index, this.size);
    }
    
    子组件
    父组件

    子组件重写performLayout方法,将尺寸大小通过冒泡通知给父组件,父组件根据id进行存储。

    相关文章

      网友评论

        本文标题:Keframe 分帧入屏: 处理flutter卡顿,优化流畅度

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