prorender怎么加快速度(你真的用对了Provider吗)(1)

对于Flutter开发的工程师们,肯定是对Provider很熟悉.

这个是官方推荐的一个状态管理插件.对于 Flutter应用 Provider的出现是提高App性能一剂良药,也是管理状态的良好工具,可是Provider真的就是一个没有副作用的状态管理利器吗? 非也! 甚至他会毁掉你的App!

完全无必要的无脑使用

首先我们以一个widgets树为例来解说:

prorender怎么加快速度(你真的用对了Provider吗)(2)

图例说明:

上图中 我们Widgets 分别是一个Root视图;还有 4个 子Widgets, 分别是:

- Text

- Chart1

- Chart2

- ListView

子Widgets 它们分别对应数据源是:

- $text

- $chartData1

- $chartData2

- $list

现在清楚我们的Widgets树层级结构和数据来源,我们开始使用Provider来进行 状态管理 ;首先我们应该在根Widget中设置 ChangeNotifierProvider 用来包裹数据源和组件视图;然后创建ChangeNotifier关联数据和变化通知;最后子视图就可以跨层级使用 ChangeNotifierProvider 包裹的数据源.简单说明一下代码逻辑:我们来看一下例子:

构建一个ChangeNotifier:

``` class ModelNotifier extends ChangeNotifier { var text; var chartData1; var chartData2; var list; updateText(newText) { text = newText ; notifyListeners(); } ...省略其余更新函数... // 获取远程数据源 getRemoteData() {} } ps: 伪代码 ```

这是一个简单的页面级的例子:

``` ... 省略非关键代码 return ChangeNotifierProvider( create: (context) => CartModel(), child: const RootWidget( Consumer(Text($text)), Collection( Consumer(Chart1($chartData1)), Consumer(Chart2($chartData2)), ), Consumer(ListView($list)), ), ) ... 省略非关键代码 ps: 伪代码 ```

以上我们将伪代码也粘贴了出来, 现在我们来演示一下数据从远程过来之后,Provider更新数据状态进而更新UI的流程.

首先,假设这是一个接口返回回来的数据,这个时候 我们将 一并获取:$text、$chartData1、$chartData2、$list的数据,那么我们想要更新4个子Widget 就必须分别调用updateText以及其他的更新视图的函数,并传递从接口获取到新的数据;这个时候我们就会发现,Provider的使用就变的没有任何意义,甚至拖沓了更新UI的时间, 我们完全可以不使用Provider 处理数据,完全可以在根视图中采用 setStates 函数来刷新整个层级树,以为此时的Provider做的事情也是刷新整个层级树视图.所以分析可以知道有几个不合理的点:

prorender怎么加快速度(你真的用对了Provider吗)(3)

改良

我们就针对两个问题进行处理,第一我们分别对接口进行拆分若干:

1. 获取Text 内容

2. 获取 两个 Charts 的内容

3. 获取 ListView 的内容

这样我们可以在获取某些数据的时候对部分组件进行更新,且在同一时间减少了整体渲染带来的大量性能损耗.

其次,对新数据的检查也是有必要的额,首先我们要增加数据新旧检验的机制,在通过检验,新数据符合渲染条件,就通知更新,否则就放弃本次的更新,这样也在一定程度上减少渲染次数.

prorender怎么加快速度(你真的用对了Provider吗)(4)

总结

Provider的合理使用是提高整体性能的保证,我们在很多的静态数据面前,其实是没有使用Provider的必要的,甚至在一些只是更新数据而不涉及UI更新的地方也需要使用注意使用Provider的非更新UI机制用法,其次就是 针对接口的调整,在庞大的数据集合中,合理地拆分接口数据可以减少对流量的浪费.也可以让用户体验更上一个台阶.

,