【Flutter】熊孩子拆组件系列之拆ListView(一)

前言

相信不少人在那个三天不打上房揭瓦的年纪中,或多或少干过各种形式的拆家活动,包括且不限于拆工具、拆玩具,甚至拆家具拆电器;

在收获一顿“皮带炒肉”之后,最大的感受除了屁股上的疼痛,就是拆解分析的快感;如果能不多不少零件的前提下再重新组装回去,除了能免于一顿胖揍之外,获得的成就感也是爆棚;

而FLutter中的各个大Widget,也是各种小Widget组合而来,按照它们的说法:Everything is a Widget

那么我今天就要看看,你有多深的道,满满的正能量,岂能被你吓到?

拆解准备

做为一名打小就拆家的资深拆家工程师,对如何拆机械拆家电也是有自己的一些心得:

比如说,初级拆家工程师,拿到小家电第一件事,就是上螺丝刀上锤子暴力拆解;按照个人经验,这种拆解方式,下场一般是一到三天内只能趴着睡觉;

而像我这种资深级别的,拿到不熟悉的小家电,第一件事就是分析构造,寻找可以上手的地方

所幸Flutter官方就提供了堪比X光的工具,能让我们比较直观的看到整个ListView的构造,那么有请DevTools给大家展示一下ListView的结构,当然,像这种初级Widget,结构不会复杂,层级无非就那么几层,看我一篇文章搞定:

ListView的Tree.gif 嗯,虽然跟我预想的有那么“亿点点”差距;但是问题不大,多写几篇水文,没啥大不了的;

那么下面结合源码,开始动工

简单分析

单单从上面devTool的DetailTree图中得到的结果,总结一下,listView的Widget树是这样:

ListViewPrimaryScrollControllerScrollableGlowingOverscrollIndicatorNotificationListener<ScrollNotification>RepaintBoundaryCustomPaintRepaintBoundary_ScrollSemantics_ScrollableScopeListenerRawGestureDetector_GestureSemanticsListenerSemanticsIgnorePointerViewportSliverPaddingMediaQuerySliverList

除了ListView本身,他还给每个item外面包了一些额外的东西:

KeyedSubtreeAutomaticKeepAliveKeepAliveNotificationListenerIndexedSemanticsRepaintBoundary

结合源码中的注释,以及我正宗的工地英语,我们可以简单的对各个widget的功能做一个基本的猜测判断:

  1. PrimaryScrollController : 用于控制ListView的基本控制器,包括滚动位置;
  2. Scrollable : A widget that scrolls. 说白了,就是个提供可滑动的组合型widget
  3. GlowingOverscrollIndicator : 提供过度滚动效果的那个
  4. NotificationListener : 各种事件的分发监听器_ScrollSemantics
  5. RepaintBoundary : 在这里和后续的所有RepaintBoundary,都只有一个作用,防止过度多次无用重绘
  6. CustomPaint : 还记得上面那个GlowingOverscrollIndicator么?你猜猜OverScroll的时候那个提示效果是谁绘制出来的?
  7. _ScrollSemantics : 根据注释来看,好像没啥大用……结合SemanticsNode来给某些地方增加语义数据(???语义数据是啥???)
  8. _ScrollableScope : 继承自InheritedWidget,那么用处很明显了,共享提供数据,至于啥数据、有啥用,以后看;
  9. Listener : 一个提供了触屏手势回调的widget;
  10. RawGestureDetector : 很经典的手势监听器,跟上面那个Listener差不多一个性质的作用
  11. _GestureSemantics : 如果需要排除一些额外的手势,那么使用这个widget
  12. Semantics : 用于给widget树增加一些语义,看注释猜测,好像单纯调试用的,比如说devTool那帮,大概~
  13. IgnorePointer : 这个就很熟悉了,触摸事件的拦截器
  14. Viewport : 展示可视范围内的widget
  15. SliverPadding : 给滑动widget类型专用的Padding小组件
  16. MediaQuery : 继承自InheritedWidget,跟那个_ScrollableScope一个性质的东西,不过在这里面放的是通用的媒体信息(???是指可视区域么???),比如说窗口大小;
  17. SliverList : 相当于ListView 基础本体?

在Item这块,组合的Widget功能猜测是这样的:

  1. KeyedSubtree : 好像就给Item包个Key,这个key默认value是index;作用不明,后续再看
  2. AutomaticKeepAlive : 说白了,缓存item,好像跟复用有点联系?
  3. KeepAlive : 跟上面的那个一个效果,具体差别是这块是标记哪些需要保活;
  4. IndexedSemantics : 看注释,又是给item加个index的,是不是因为KeyedSubtree有存在不是index当key的情况,所以index信息放这里?

整理一下,下面将会对这几个widget做下研究

  1. PrimaryScrollController(控制器,研究整体流程肯定要涉及这块)
  2. Scrollable (滑动本体)
  3. _ScrollableScope(看下里面保存的啥数据)
  4. Viewport(视窗肯定是相关部分)
  5. SliverList(列表本体)

item这块:

  1. KeyedSubtree(看下到底啥用)
  2. KeepAlive(保活部分,可能涉及复用?)
  3. IndexedSemantics(这个index保存的作用是?)

目录搞定,开工

猜你喜欢

转载自juejin.im/post/7016538861580845063