繁体   English   中英

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

[英]How to avoid unnecessary rebuilds while using provider in flutter?

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

例子

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.increment(),
    );

  }
}


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.decrement(),
    );

  }
}

现在,如果我单击MyIncreaseButton小部件以增加该值,即使我没有单击它,也会构建MyDecreaseButton小部件。

反之亦然,如果我单击MyDecreaseButton小部件以减小该值,即使我没有单击它,也会构建MyIncreaseButton小部件。

我的期望是:

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

有多种解决方案:

  • 使用context.read或将listen: false传递给Provider.of
RaisedButton(
  onPressed: () {
    context.read<MyModel>().increment();
    // alternatively, do:
    Provider.of<MyModel>(context, listen: false).increment();
  },
  child: Child(),
);
  • 使用context.select
Widget build(context) {
  final increment = context.select((MyModel m) => m.increment);

  return RaisedButton(
    onPressed: increment,
    child: Child(),
  ); 
}
  • 使用Selector
Widget build(context) {
  return Selector<MyModel, VoidCallback>(
    selector: (_, model) => model.increment,
    builder: (_, increment) {
      return RaisedButton(
        onPressed: increment,
        child: Child(),
      );
    },
  );
}

选择器正是您所需要的。 使用选择器,您可以过滤更新。 例如,仅在名称更改时更新,您可以执行以下操作

Selector<AppStore, String>(
  selector: (_, store) => store.name,
  builder: (_, name, __) {
    return Text(name);
  },
);

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

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 increaent() {
    _num = _num + 1;
    notifyListeners();
  }

  void decrement() {
    _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.increment(),
    );
  }
}

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.decrement(),
    );
  }
}

考虑使用选择器Selector

你也可以从这里阅读文件

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM