Flutter 动态化热更新的思考与实践(六)---- 动态列表滚动优化
上一篇文章中提到了一个重要的概念----上下文对象树,没有详细说明,今天写一个短篇来解释一下。
顾名思义,上下文对象树(AstContext Tree)是以树结构来组织上下文对象(AstContext),在Runtime执行过程中,AstContext 贯穿整个执行过程,其中存储了当前代码作用域中的变量以及各种状态等,使各个代码作用域中的数据和状态相互隔离不受影响,这里的代码作用域基本就泛指一个代码块中的内容,同局部变量和全局变量的作用域是一样的。
我们在编码过程中会大量涉及局部变量和全局变量的操作,在Runtime执行解析Ast时,需要能准确的识别当前操作的变量和状态,同时还要能追溯当前代码块上一层代码块的变量和状态,因为在编程语言中下一层代码块是可以使用上一层代码块的变量的。所以综上分析,既要隔离代码的作用域,还要能追溯上一层代码块的变量状态,树结构是最合适不过的了。
实际上这部分走了一点弯路,最开始的设计是栈结构,想模拟的是进入代码块时候对局部变量入栈,代码块执行完变量出栈,这部分变量就没有用了。
但是这种设计有一种情况无法解决,就是函数闭包,在闭包中可能还会用到其代码块中的变量,那么待执行闭包中的代码逻辑时,就找不到该变量了。
那么,在树结构中是如何运行并解决这个问题的:
树结构中,即使代码块执行完成,其叶子节点仍然存在,在执行闭包的过程中,可以从当前叶子结点开始向上追溯查找对应的变量:
追溯查找过程中,第一次匹配到的变量,既是所要操作的变量,这也是模拟了变量名相同时优先取最近的局部变量值。不过这种编码习惯不太好,IDE一般都会给警告⚠️,只是一旦有这种情况,我们可以准确的取到想要的变量。
同样,闭包这种特殊情况在树结构中也存在一个问题,就是叶子结点的释放,目前没有想到好的释放策略,因为不清楚闭包会在何时执行,现在只是在dispose中释放整个AstContext Tree,在此之前树中存储的变量状态会一直存在于内存中,对内存的占用会有些影响,所以对于循环代码块的情况需要特殊处理,避免将其中的变量存在AstContext Tree中,实现思路是在解析对应Ast语法node中做处理,在此不多表。