Modifier 我们第三章就介绍过,回头去看了一眼,呃...
如图 Modifier 共有三个直接实现子类
- 伴生对象 Modifier ,方便使用 Modifier.xxx().xxx() 形式调用
- Element 单个 Modifier ,它的直接实现子类都是接口,相当于按功能分类,实现具体功能的 Modifier 都在下一级
- CombinedModifier 包装类,配合
Modifier.then方法将 Modifier.xxx().xxx() 中的每个 Modifier 一层一层包装在一起
Modifier 包装与遍历
包装
Modifier 伴生对象的 then() 方法是返回参数中的 Modifer 对象
companion object : Modifier {
override infix fun then(other: Modifier): Modifier = othe
}
Modifier then() 方法的默认实现是当参数不是 Modifier 伴生对象时,将参数与当前 Modifer 对象使用 CombinedModifier 组合在一起
@Stable
interface Modifier {
infix fun then(other: Modifier): Modifier
if (other === Modifier) this else CombinedModifier(this, other)
}
CombinedModifier 的 outer 和 inner 属性配合 then() 方法对 Modifier 进行包装
class CombinedModifier(
private val outer: Modifier
private val inner: Modifier
) : Modifier {}
我们以下面的代码为例进行本问的分析。
modifier = Modifier.size(200.dp,100.dp).background(Color.LightGray).padding(8.dp)
size() 、background()、padding() 这些拓展方法实现都是使用 then() 方法与对应的 Modifier 对象包装后返回一个 CombinedModifier 对象
fun Modifier.size(width: Dp, height: Dp) = this.then( SizeModifier(/*...*/) )
我们在 Compose 函数中使用的 modifier 参数就这样一层一层的包装在了一起。
遍历
modifier 既然是包装起来的对象,那么为什么这里成了遍历而不是拆装呢?
我们来看一下 Element 和 CombinedModifier 中 foldIn()的源码( foldOut()省略 )
interface Element : Modifier {
override fun <R> foldIn(initial: R, operation: (R, Element) -> R): R =
operation(initial, this)
}
class CombinedModifier(
private val outer: Modifier,
private val inner: Modifier
) : Modifier {
override fun <R> foldIn(initial: R, operation: (R, Modifier.Element) -> R): R =
inner.foldIn(outer.foldIn(initial, operation), operation)
}
将包装 modifier inner 和 out 看成指针, modifier 会变成二叉树的结构
在 CombinedModifier 中 foldIn() 并不会执行 operation() ,而是去调用 inner.foldIn() 。如下图 CombinedModifier 对象也可以看成指针的一部分
foldIn() 方法的作用是 : 以 inital 为初始值从最内层包装 按照 outer -> inner 的顺序依次使用 modifier 中的每一个 Modifer 对象来执行 operation 函数,并将每次的执行结果作为参数传递到下一个 operation 函数 。
val str = modifier.foldIn("Start"){ str,element->
"$str -> ${element.javaClass.simpleName}"
}
Log.e(TAG, "foldIn: $str")
foldIn: Start -> SizeModifier -> Background -> PaddingModifier
LayoutNode#setModifier
有了上面的铺垫我们就可以继续 Compose 函数转换成 LayoutNode 中第三步 setModifier 的分析了。
internal class LayoutNode : Measurable, Remeasurement, OwnerScope, LayoutInfo, ComposeUiNode {
//set modifier 相关
internal val innerLayoutNodeWrapper: LayoutNodeWrapper = InnerPlaceable(this)
private val outerMeasurablePlaceable = OuterMeasurablePlaceable(this, innerLayoutNodeWrapper)
override var modifier: Modifier = Modifier
set(value) {
if (value == field) return
if (modifier != Modifier) {
require(!isVirtual) { "Modifiers are not supported on virtual LayoutNodes" }
}
field = value
//......
// innerLayoutNodeWrapper 为初始值,foldOut 从最外层 inner-> outer 的顺序遍历 modifier
val outerWrapper = modifier.foldOut(innerLayoutNodeWrapper) { mod, toWrap ->
var wrapper = toWrap
//......
val delegate = reuseLayoutNodeWrapper(mod, toWrap)
if (delegate != null) {
//......
} else {
//......
//根据不同的类型将 modifier 与 wrapper 包装成 DelegatingLayoutNodeWrapper<T : Modifier.Element> 对象
if (mod is LayoutModifier) {
wrapper = ModifiedLayoutNode(wrapper, mod).assignChained(toWrap)
}
//......
}
wrapper
}
outerWrapper.wrappedBy = parent?.innerLayoutNodeWrapper
//将包装了 modifier 的 outerWrapper 对象 赋值给 outerMeasurablePlaceable.outerWrapper
outerMeasurablePlaceable.outerWrapper = outerWrapper
//......
}
}
LayoutNode#setModifier
- 以 innerLayoutNodeWrapper 为初始值遍历 modifier 将每个 Modifier 对象转换成 LayoutNodeWrapper 对象包装起来得到 outerWrapper
- 将 outerWrapper 赋值给 outerMeasurablePlaceable.outerWrapper
InnerPlaceable、 OuterMeasurablePlaceable 、ModifiedLayoutNode:DelegatingLayoutNodeWrapper 都实现了 measure() 方法,相关内容我们下一节介绍。