UME: Widget层级展示
Widget层级展示
今天我们来看下UME中的Widget层级展示是如何实现的
先来看一下这个功能是什么样子的, 点击某个widget,会跳转到childenElements页面
当我们点击某个element时会跳进一个详情页面
果不其然在widget_detail_inspector.dart这个文件中我们看到了熟悉的代码
void _inspectAt(Offset? position) {
final List<RenderObject> selected = HitTest.hitTest(position);
setState(() {
selection.candidates = selected;
});
}
还记得这个方法是干嘛的么,没错就是获取所有包含点击位置的widget,那么接下来要做的就是把这些数据显示成一个列表,再往下看在__InfoPageState
中传入了selection.currentElement!.debugGetDiagnosticChain()
并将element转换成了detailmodel,
搜索通过RegExp
中的hasMatch
方法进行匹配文字
var regExp = RegExp("$query", caseSensitive: false);
if (regExp.hasMatch(model.element.widget.toStringShort())) {
infoList.add(model);
}
点击element后会走到_DetailContent
创建详情页的布局,其中使用了一个FutureBuilder进行异步创建,并写了一个异步方法getInfo
Future<List<String>> getInfo() async {
Completer<List<String>> completer = Completer();
String string = element.renderObject!.toStringDeep();
List<String> list = string.split("\n");
completer.complete(list);
return completer.future;
}
将renderOject转成字符串并分割成数组通过list进行显示。
UME的层级展示还是比较简单的,额外在讲一下FutureBuilder这个组件
FutureBuilder
简单介绍及例子
这个组件还是比较简单的内容也比较少,先看下构造函数
const FutureBuilder({
Key? key,
this.future,
this.initialData,
required this.builder,
}) : assert(builder != null),
super(key: key);
只有三个参数future
、initialData
、builder
,future就是我们需要传入的异步方法,initialData是用来初始化的数据,也可以不用传入,builder是用来返回future结果的,接下来我们看个例子
new FutureBuilder<String>(
future: _calculation, // 用户定义的需要异步执行的代码,类型为Future<String>或者null的变量或函数
builder: (BuildContext context, AsyncSnapshot<String> snapshot) { //snapshot就是_calculation在时间轴上执行过程的状态快照
switch (snapshot.connectionState) {
case ConnectionState.none: return new Text('Press button to start'); //如果_calculation未执行则提示:请点击开始
case ConnectionState.waiting: return new Text('Awaiting result...'); //如果_calculation正在执行则提示:加载中
default: //如果_calculation执行完毕
if (snapshot.hasError) //若_calculation执行出现异常
return new Text('Error: ${snapshot.error}');
else //若_calculation执行正常完成
return new Text('Result: ${snapshot.data}');
}
},
)
snapshot.connectionState就是异步函数future的执行状态,总共有四种执行状态: 1.ConnectionState.none 未开始 2.ConnectionState.active (还未使用过,后续学习一下) 3.ConnectionState.waiting 加载中 4.ConnectionState.done 加载完毕
防重绘
如果FutureBuilder的父组件重绘,那么FutureBuilder也会进行重绘,也会导致异步方法被重新调用,引起资源浪费,通过查看源码可以发现FutureBuilder的重绘机制是通过future是否相等进行控制的,那么如果我们传入额future是不变的就可以防止FutureBuilder进行重绘,所以我们可以引入一个变量来接口future方法,并将变量传入FutureBuilder
var _mFuture;
@override
void initState() {
// TODO: implement initState
super.initState();
_mFuture = _future();
}
_future() async{
...
}
FutureBuilder(
future: _mFuture,
...
)
好了今天的源码查看就到这了, 作为Flutter届的一个小学生,希望大家多多指教,有问题的地方一起讨论
转载自:https://juejin.cn/post/7026321246975442958