Flutter bloc 模式多次重复调用函数

Posted

技术标签:

【中文标题】Flutter bloc 模式多次重复调用函数【英文标题】:Flutter bloc pattern repeat calling function many times 【发布时间】:2020-03-11 17:49:20 【问题描述】:

我正在尝试在颤振应用程序中使用 bloc 模式我在返回 Scaffold() 之前在构建函数的主体内编写代码;如下

@override
  Widget build(BuildContext context) 
    final ProductsController pController = Provider.of<ProductsController>(context);
    pController.addProducts();
    return Scaffold();

一切都是完美的,但功能 addPrducts() 调用了太多次它看起来下面的代码重复了很多次

pController.addProducts();

这是 ProductsContoller 类的结构

class ProductsController extends ChangeNotifier 
List<Products> _products=List();
AppDatabase appDB=AppDatabase();
  List<Products> get products=>_products;
addProducts() 
      appDB.getFromTable(AppDatabase.TBL_PRODUCTS).then((rows)
      rows.forEach((row)
        Products product=Products.fromJson(row);
        _products.add(product);


      );
      notifyListeners();
    );
  

【问题讨论】:

你在构建方法中使用setState吗? 不,我使用 bloc 来避免使用 setState 【参考方案1】:

您必须定义在其他类(有状态或无状态)中使用您的列表的小部件。

例如,如果您在 ListView 中使用 List,则必须为您的 ListView 创建一个无状态类,并在该类中监视列表。

    class ProductList extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return GridView.builder(
      gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
        maxCrossAxisExtent: 260,
        childAspectRatio: 3 / 4.6,
      ),
      itemCount: context.watch<ProductsController >().productPjo.listProduct.length,
      shrinkWrap: true,
      itemBuilder: (_, i) 
        return  ItemProduct(context.watch<ProductsController >().productPjo.listProduct[i]);
      ,
    );
  

【讨论】:

【参考方案2】:

如果你想做一些操作,比如在有状态小部件中只获取一次屏幕数据,那么你可以使用 void didChangeDependencies() 和布尔标志。

didChangeDependencies() 也会在 initState 之后立即调用。 当此 State 对象的依赖项发生更改时也会调用。从此方法调用 BuildContext.dependOnInheritedWidgetOfExactType 是安全的。

final ProductsController pController
var _isLoadingForFirstTime = true;

@override
void initState() 
    super.initState();


@override
  void didChangeDependencies() 
    if (_isLoadingForFirstTime) 
       pController = Provider.of<ProductsController>(context);
       pController.addProducts();
    
    _isLoadingForFirstTime = false;
    super.didChangeDependencies();


@override
  Widget build(BuildContext context) 
    return Scaffold(); // You Screen contents here

【讨论】:

【参考方案3】:

如果你的函数应该只被调用一次,你应该尝试覆盖initState() 方法并在那里调用它。如果您的类扩展了 StatefulWidget 您的 build(BuildContext context) 方法可能会被多次调用。

final ProductsController pController

@override
void initState() 
    pController = Provider.of<ProductsController>(context);
    pController.addProducts();

    super.initState();

【讨论】:

是什么导致构建方法多次调用?? 框架在多种不同情况下调用此方法: 在调用 initState 之后。调用 didUpdateWidget 之后。在收到对 setState 的调用后。在此 State 对象的依赖项发生更改后(例如,先前构建所引用的 InheritedWidget 发生更改)。在调用 deactivate 然后将 State 对象重新插入到另一个位置的树中。 api.flutter.dev/flutter/widgets/State/build.html 你的方式给这个异常 inheritFromWidgetOfExactType(_Provider) 或 inheritFromElement() 被称为 I/flutter (6563):在 _ReportState.initState() 完成之前。 _ReproSate 是我的 Class 继承的 statefulWidget

以上是关于Flutter bloc 模式多次重复调用函数的主要内容,如果未能解决你的问题,请参考以下文章

Dart/Flutter - 回调函数的收益

无法使用颤振 Bloc 模式更新小部件外部的 UI

Flutter - 了解 Provider、Bloc 的生命周期以及何时处理流 [重复]

BLoC:多次调用监听回调

在不可变状态不实用的情况下使用 Bloc 模式

Flutter BLoC 模式 - 如何在流事件后导航到另一个屏幕?