侧边栏壁纸
博主头像
NewTab

记录生活,分享知识

  • 累计撰写 12 篇文章
  • 累计创建 14 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

Flutter进入页面卡顿如何优化

NewTab
2023-07-24 / 0 评论 / 0 点赞 / 128 阅读 / 452 字 / 正在检测是否收录...

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);
}
0

评论区