Flutter 图片选择器性能优化实践

Flutter 图片选择器性能优化

##:使用Flutter实现了一个图片选择器控件,集成到Hilight里面。 自测发现在一些低端机上会有卡顿现象,需要优化下才能提测

git项目地址

ui截图

优化项目:

1. 局部刷新

最先想到的是这个,每次数据变动只刷新对应变动的UI,避免直接用 setState 全屏刷新。具体是实现是:

  • 尽可能使用const。 使用const的 对象只会实例一次
  • 把 build方法抽取出 独立控件,构造函数 尽量设置成const.
  • 使用ValueNotifier 来实现局部刷新。比对了几种状态管理的模型,觉得这个地方ValueNotifier会比较合适
//初始化包装:
  ValueNotifier segmentValue = ValueNotifier(0);
//数据更改:
    segmentValue.value = value;

//触发UI刷新:
      child: ValueListenableBuilder(
        valueListenable: segmentValue,
        builder: (context, value, child) {
          return Stack(
            alignment: Alignment.topCenter,
            children: [
              Center(
                child: _segment(),
              ),
              Positioned(
                top: 16,
                child: btnClose(),
                right: 16,
              )
            ],
          );
        },
      ),

2. 分页优化

  • 修改分页触发时机,提前点加载。
scroll.metrics.pixels / scroll.metrics.maxScrollExtent > 0.7
  • 只接收ScrollEndNotification事件,来实现 滑动停止时加载
 return NotificationListener(
      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 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 recentFolder;

  @override
  void initState() {
    super.initState();
    recentFolder = getRecentFolder();
  }

参考

  • 防止FutureBuilder不必要重绘的两种方法
  • Flutter开发性能提升之:如何避免Widget重复Build

你可能感兴趣的:(Flutter,Java)