如何提高你Flutter app的性能

原文地址

1.不要将你的界面组件切分到方法中

如:

class MyHomePage extends StatelessWidget {
    Widget _buildHeaderWidget() {
        return Container(...);
    }
    Widget _buildBodyWidget() {
        return Container(...);
    }
    Widget _buildFooterWidget() {
        return Container(...);
    }
    
    @overrider
    Widget build(BuildContext context) {
        return Scaffold(
            body:Column(
                children:[
                    _buildHeaderWidget(),
                    _buildBodyWidget(),
                    _buildFooterWidget(),
                ],
            ),
        );
    }
}

每次我们改变或刷新整体的widget时,分割在method里的widget也会被重构一次,这导致了对cpu资源的浪费。

使用提取界面组件为自定义类的方式代替

如:

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          _HeaderWidget(),
          _BodyWidget(),
          _FooterWidget(),
        ],
      ),
    );
  }
}

class _HeaderWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(...);
  }
}

class _BodyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(...);
  }
}

class _FooterWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(...);
  }
}

Stateful/Stateless widget 有一种特别的缓存机制(基于key、widget type、属性),这使得它们只会在必要的时候重构。

这一点,我感觉,如果你不设置key,好像还是会重构。

2.不要反复地重构所有的widgets

核心思想是指,尽量只重构必要的widget。
少用setState

替代方案

ValueNotifier

class _MyHomePageState extends State {

  final ValueNotifier notifier = ValueNotifier(false);

  @override
  void dispose(){
    notifier.dispose();
    super.dispose;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ValueListenableBuilder(
        valueListenable: notifier,
        child: _Child(),
        builder: (_,v,child) => Offstage(
          offstage: v,
          child: child,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          notifier.value = !notifier.value;
        },
      ),
    );
  }
}

class _Child extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('_Child build');
    return Center(child: Text('hello'),);
  }
}

ValueNotifiervalue发生变化时,会自动通知ValueListenableBuilder执行builder传入的回调,简单易用。
如果不使用ValueListenableBuilderchild属性,而是直接将_Child()构建在builder回调里,_Child将在每次notifier的值改变时被重构。

provider框架中就继承了ValueNotifier的父类 ChangeNotifier

将不变的widget用const修饰

抓住核心思想(减少不必要的重构)就行了。

3.在使用长列表时,尽可能的使用itemExtent属性

这一点其实在任何时候都适用,尽可能的给你的widget一个大小,可以节省cpu计算widget大小的时间。

4.不要再AnimatedBuilder中重构不必要的widget

AnimatedBuilder的重构方式和上面ValueListenableBuilder类似,都是会执行builder回调。

5.不要使用Opacity特别是在动画里

Opacity用在动画里时,会使界面每一帧都重构。这一点闲鱼团队也提过。
替代方案

FadeTransition

AnimatedOpacity

你可能感兴趣的:(如何提高你Flutter app的性能)