1.卡顿的原因是什么?
当进入页面时需要解析大量的json数据,而导致页面进入动画卡顿.
2.如何解决?
json 可以开线程解析,然后配合延迟加载渲染 UI,大部分情况下,json 复杂,意味着 UI 也会很复杂,如果 UI 不复杂,则不需要延迟加载
3.如何使用延迟加载
import 'package:flutter/cupertino.dart';
/// call prepareData -> afterLayout -> onLazyLoad
mixin LazyLoadState<T extends StatefulWidget> on State<T> {
@override
void initState() {
prepareData();
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
afterLayout();
var route = ModalRoute.of(context);
void handler(status) {
if (status == AnimationStatus.completed) {
route?.animation?.removeStatusListener(handler);
onLazyLoad();
}
}
if (route == null ||
route.animation == null ||
route.animation!.status == AnimationStatus.completed) {
onLazyLoad();
} else {
route.animation!.addStatusListener(handler);
}
});
}
//页面已经完全进入之后调用
void onLazyLoad() {}
//initState 之后,页面进入第一帧之后调用
void afterLayout() {}
//initState之前调用
void prepareData() {}
}
4.举个解析大量 json 数据的例子
//这个例子中,延迟加载不是非必需的,但是开线程解析 json 是必须的
class _MyHomePageState extends State<MyHomePage>
with LazyLoadState<MyHomePage> {
//假设DataBean 的数据结构非常复杂,解析 json 至少要1s
DataBean? dataBean;
dynamic json;
bool hasLazyLoaded = false;
void render() {
setState(() {});
}
@override
void prepareData() {
Future.delayed(const Duration(milliseconds: 500), () {
return ["A", "B", "C"];
}).then((value) {
json = value;
//返回 json 之后开线程解析,因为开线程解析不会卡顿 UI,如果不开线程解析json,就需要把解析 json 功能放在页面全部进入之后再操作
compute(toDataBean, json).then((value) {
dataBean = value;
//等到页面全部进入之后再渲染 UI,因为 UI 也特别复杂,这里也可以采用分段渲染,会减少 UI渲染带来的 UI 卡顿问题
if (hasLazyLoaded) {
render();
}
});
});
}
@override
void onLazyLoad() {
hasLazyLoaded = true;
if (dataBean != null) {
render();
}
}
@override
Widget build(BuildContext context) {
if (!hasLazyLoaded) {
return const CupertinoActivityIndicator();
}
return const Scaffold();
}
}
DataBean toDataBean(dynamic json) {
return DataBean.fromJson(json);
}
评论区