Flutter 图片选择器性能优化
##:使用Flutter实现了一个图片选择器控件,集成到Hilight里面。 自测发现在一些低端机上会有卡顿现象,需要优化下才能提测
优化项目:
1. 局部刷新
最先想到的是这个,每次数据变动只刷新对应变动的UI,避免直接用 setState 全屏刷新。具体是实现是:
- 尽可能使用const。 使用const的 对象只会实例一次
- 把 build方法抽取出 独立控件,构造函数 尽量设置成const.
- 使用ValueNotifier 来实现局部刷新。比对了几种状态管理的模型,觉得这个地方ValueNotifier会比较合适
//初始化包装:
ValueNotifier<int> segmentValue = ValueNotifier(0);
//数据更改:
segmentValue.value = value;
//触发UI刷新:
child: ValueListenableBuilder(
valueListenable: segmentValue,
builder: (context, value, child) {
return Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Center(
child: _segment(),
),
Positioned(
top: 16,
child: btnClose(),
right: 16,
)
],
);
},
),
2. 分页优化
- 修改分页触发时机,提前点加载。
scroll.metrics.pixels / scroll.metrics.maxScrollExtent > 0.7
- 只接收ScrollEndNotification事件,来实现 滑动停止时加载
return NotificationListener<ScrollEndNotification>(
onNotification: (ScrollEndNotification scroll) {
_handleScrollEvent(scroll);
return true;
},
- 避免 notification 通知重复触发,引入loading来判断,如果正在请求分页,不重复请求
_handleScrollEvent(ScrollNotification scroll) {
if (scroll.metrics.pixels / scroll.metrics.maxScrollExtent > 0.7) {
if (!isEnd && !loading) {
_fetchNewMedia(pathEntity);
}
}
}
_fetchNewMedia(AssetPathEntity pathEntity) async {
loading = true;
List<AssetEntity> media =
await pathEntity.getAssetListPaged(currentPage, 60);
if (media.isEmpty) {
isEnd = true;
return;
} else {
setState(() {
_mediaList.addAll(media);
currentPage++;
loading = false;
});
}
}
完整的例子可以参考: git地址
内存优化
- 由于messageChannel会被频繁调用,因此native那边需要设置一个线程池来缓冲请求。
- flutter 实现LRU 缓存功能,使用内存缓存已经获取的图片,加快图片显示速度
- 根据产品UI,确定要加载的图片宽高,来加载图片。
//默认GridView小图的宽:
MediaQuery.of(context).size.width / (3 * 2);
//预览图的宽:
MediaQuery.of(context).size.width
页面初始化优化
- 尽量在 widget的 initState里面 请求数据,避免build里面重复请求
- 把FutureBuild的初始化放在 initState里面,设置为成员变量,减少重复调用
Future<AssetPathEntity> recentFolder;
@override
void initState() {
super.initState();
recentFolder = getRecentFolder();
}