Flutter 在颤振中使用提供程序时,如何避免不必要的重建?

Flutter 在颤振中使用提供程序时,如何避免不必要的重建?,flutter,dart,provider,Flutter,Dart,Provider,我正在我的应用程序中使用,但我面临着不必要的构建 范例 class AllWidget extends StatelessWidget{ @override Widget build(BuildContext context){ print('state build called'); return ChangeNotifierProvider( builder: (_) => MyCounter(), child:

我正在我的应用程序中使用,但我面临着不必要的构建

范例

class AllWidget extends StatelessWidget{

  @override
  Widget build(BuildContext context){
    print('state build called');
    return ChangeNotifierProvider(
            builder: (_) => MyCounter(),
            child: Column(children: <Widget>[
                  MyCounterText(),
                  MyIncreaseButton(),
                  MyDecreaseButton(),
            ],
          ),
    );
  }
}

class MyCounterText extends StatelessWidget{

  @override
  Widget build(BuildContext context) {
    final myCounter = Provider.of<MyCounter>(context, listen: false);
    print('MyCounterText');
    return Text(myCounter.num.toString());

  }
}

class MyIncreaseButton extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    final myCounter = Provider.of<MyCounter>(context, listen: false);
    print('MyIncreaseButton');
    return RaisedButton(
      child: Text('Increase +'),
      onPressed: ()=> myCounter.increament(),
    );

  }
}


class MyDecreaseButton extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    final myCounter = Provider.of<MyCounter>(context, listen: false);
    print('MyDecreaseButton');
    return RaisedButton(
      child: Text('Decrease -'),
      onPressed: ()=> myCounter.decreament(),
    );

  }
}
class AllWidget扩展了无状态widget{
@凌驾
小部件构建(构建上下文){
打印('state build called');
返回ChangeNotifierProvider(
生成器:(\u)=>MyCounter(),
子项:列(子项:[
MyCounterText(),
MyIncreaseButton(),
MyDecreaseButton(),
],
),
);
}
}
类MyCounterText扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
final myCounter=Provider.of(context,listen:false);
打印('MyCounterText');
返回文本(myCounter.num.toString());
}
}
类MyIncreaseButton扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
final myCounter=Provider.of(context,listen:false);
打印(“MyIncreaseButton”);
返回上升按钮(
子项:文本('增加+'),
onPressed:()=>myCounter.increment(),
);
}
}
类MyDecreaseButton扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
final myCounter=Provider.of(context,listen:false);
打印(“MyDecreaseButton”);
返回上升按钮(
子项:文本('减少-'),
按下时:()=>myCounter.decreament(),
);
}
}
现在,如果我点击
MyIncreaseButton
小部件来增加值,
MyDecreaseButton
小部件也会生成,即使我没有点击它

反之亦然,如果我点击
MyDecreaseButton
widget来减少值,那么
myEncreaseButton
widget也会生成,即使我没有点击它

我的期望是:


单击
MyIncreaseButton
小部件时,不应构建
MyDecreaseBtton
小部件。

有多种解决方案:

  • 使用
    上下文。阅读
    或将
    侦听:false
    传递给
    提供者。of
RaisedButton(
已按下:(){
context.read().increment();
//或者,请:
Provider.of(context,listen:false).increment();
},
child:child(),
);
  • 使用
    上下文。选择
小部件构建(上下文){ 最终增量=上下文。选择((MyModel m)=>m.increment); 返回上升按钮( 按:增量, child:child(), ); }
  • 使用
    选择器
小部件构建(上下文){ 返回选择器( 选择器:(u,model)=>model.increment, 建造商:(ux,增量){ 返回上升按钮( 按:增量, child:child(), ); }, ); }
选择器就是您所需要的。使用选择器,您可以筛选更新。 例如,要仅在名称更改时更新,可以执行以下操作

Selector<AppStore, String>(
  selector: (_, store) => store.name,
  builder: (_, name, __) {
    return Text(name);
  },
);
选择器(
选择器:(_,store)=>store.name,
建筑商:(uu,名称,uuu){
返回文本(名称);
},
);

我只是通过如下编辑代码来避免不必要的渲染:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';

class MyCounter with ChangeNotifier {
  int _num = 0;

  int get num => _num;

  set num(int n) {
    _num = n;
    notifyListeners();
  }

  void increament() {
    _num = _num + 1;
    notifyListeners();
  }

  void decreament() {
    _num = _num - 1;
    notifyListeners();
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('root build called');
    return ChangeNotifierProvider(
        builder: (context) => MyCounter(),
        child: MaterialApp(
          title: 'MyAppJan',
          home: Scaffold(
            appBar: AppBar(title: Text('Home')),
            body: AllWidget(),
          ),
          theme: ThemeData(primarySwatch: Colors.orange),
        ));
  }
}

class AllWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('state build called');
    return Center(
      child: Column(
        children: <Widget>[
          MyCounterText(),
          SizedBox(height: 10),
          MyIncreaseButton(),
          SizedBox(height: 10),
          MyDecreaseButton(),
        ],
        mainAxisAlignment: MainAxisAlignment.center,
        mainAxisSize: MainAxisSize.min,
      ),
    );
  }
}

class MyCounterText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('MyCounterText');
    return Consumer<MyCounter>(
      builder: (context, myCounter, _) {
        return Text(myCounter.num.toString());
      },
    );
  }
}

class MyIncreaseButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _items = Provider.of<MyCounter>(context,listen: false);
    print('MyIncreaseButton');
    return RaisedButton(
      child: Text('Increase ++'),
      onPressed: () => _items.increament(),
    );
  }
}

class MyDecreaseButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _items = Provider.of<MyCounter>(context,listen: false);
    print('MyDecreaseButton');
    return RaisedButton(
      child: Text('Decrease --'),
      onPressed: () => _items.decreament(),
    );
  }
}
导入“包装:颤振/材料.省道”;
导入“包:provider/provider.dart”;
进口“包装:颤振/基础.dart”;
使用ChangeNotifier类MyCounter{
int _num=0;
int get num=>\u num;
set num(int n){
_num=n;
notifyListeners();
}
无效增量(){
_num=_num+1;
notifyListeners();
}
void decreament(){
_num=_num-1;
notifyListeners();
}
}
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
打印('root-buildcalled');
返回ChangeNotifierProvider(
生成器:(上下文)=>MyCounter(),
孩子:MaterialApp(
标题:“MyAppJan”,
家:脚手架(
appBar:appBar(标题:Text('Home')),
正文:AllWidget(),
),
主题:主题数据(原始样本:颜色。橙色),
));
}
}
类AllWidget扩展了无状态Widget{
@凌驾
小部件构建(构建上下文){
打印('state build called');
返回中心(
子:列(
儿童:[
MyCounterText(),
尺寸箱(高度:10),
MyIncreaseButton(),
尺寸箱(高度:10),
MyDecreaseButton(),
],
mainAxisAlignment:mainAxisAlignment.center,
mainAxisSize:mainAxisSize.min,
),
);
}
}
类MyCounterText扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
打印('MyCounterText');
退货消费者(
生成器:(上下文,myCounter,389;){
返回文本(myCounter.num.toString());
},
);
}
}
类MyIncreaseButton扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
final _items=Provider.of(上下文,侦听:false);
打印(“MyIncreaseButton”);
返回上升按钮(
子项:文本('Increase++'),
按下时:()=>\u items.increment(),
);
}
}
类MyDecreaseButton扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
final _items=Provider.of(上下文,侦听:false);
打印(“MyDecreaseButton”);
返回上升按钮(
子项:文本('减少--'),
按下时:()=>_items.decreament(),
);
}
}

您的示例不清楚。你能找出一些实际运行的问题吗?@RémiRousselet,你好,谢谢你,请再看看我编辑的问题。如您所见,我有树状小部件,我想要更新widget2,因此只有这个小部件应该是build(render)而不是widget1和widget3,如果您使用了
react native
有一个名为
shouldcomponentupdate(np,ns)
的生命周期函数,它让我们避免不属于它的不必要的渲染。​ 为什么我担心一个大的列表,其中的每一项都是一个小部件,那么为什么我要问这个问题:我的ListView有1000项,我更新了