10

我想使用provider( ChangeNotifierProvider) 和ChangeNotifier管理应用程序状态。但是我如何才能从另一个模型中的一个模型访问状态呢?

用例:在聊天应用程序中,一种用于存储用户信息的模型。其他模型使用用户信息(例如用户 ID)来调用数据库(Firestore)并获取聊天数据流。

例如:

class Model1 extends ChangeNotifier {
  final List<Item> items = [];

class Model2 extends ChangeNotifier {
//Access items from Model1 here
items;

这可能吗?我不喜欢有很大的模型,因为很难维护。



谢谢!

4

5 回答 5

12

使用provider,一个模型不会访问另一个模型。

相反,您应该使用ProxyProvider, 来组合来自其他人的模型。

你的模型看起来像:

class Foo with ChangeNotifier {
  int count = 0;

  void increment() {
    count++;
    notifyListeners();
  }
}

class Bar with ChangeNotifier {
  int _count;
  int get count => _count;
  set count(int value) {
    if (value != count) {
      _count = value;
      notifyListeners();
    }
  }
}

然后你可以使用ChangeNotifierProxyProvider这种方式(假设你的小部件树中有一个更高的`ChangeNotifierProvider):

ChangeNotifierProxyProvider<Foo, Bar>(
  initialBuilder: (_) => Bar(),
  builder: (_, foo, bar) => bar
    ..count = foo.count, // Don't pass `Foo` directly but `foo.count` instead
)
于 2019-06-27T20:39:57.073 回答
4

v4开始,ChangeNotifierProxyProvider提供者可以像这样构造:

ChangeNotifierProxyProvider<Foo, Bar>(
  create: (_) => Bar(),
  update: (_, foo, bar) => bar
    ..count = foo.count,
)

请注意,initialBuilder:已更改为create:builder:update:

于 2020-03-06T08:17:03.637 回答
1

我试图简单地实现这一点。

提供程序版本 ^4.3.3

这里我举了一个简单的例子

主要.dart

ChangeNotifierProxyProvider<AuthProvider, ProductsProvider>(
       create: (context) => ProductsProvider(),
       update: (context, auth, previousProducts) => previousProducts
            ..update(auth.token, previousProducts.items == null ? [] : previousProducts.items),
),

authProvider.dart

class AuthProvider with ChangeNotifier {
  String _token;
  // _token is a response token.
  String get token {
    return _token;
}

productsProvider.dart

产品是一类单品

class ProductsProvider with ChangeNotifier {
  List<Product> _items = [];
  String _authToken;
  void update(authToken, items) {
    _items = items;
    _authToken = authToken;
    notifyListeners();
  }
}

产品.dart

class Product with ChangeNotifier {
  final String id;
  final String title;
  final String description;
  final double price;
  final String imageUrl;
  bool isFavorite;

  Product({
    @required this.id,
    @required this.title,
    @required this.description,
    @required this.price,
    @required this.imageUrl,
    this.isFavorite = false,
  });
}
于 2021-03-02T05:56:16.710 回答
0

我做了这样的事情。我们正在传递“项目”。

>class Model1 extends ChangeNotifier {
  final List<Item> items = [];
}

>class Model2 extends ChangeNotifier {
//Access items from Model1 here
 Model1 items;
Model2(this.items);
// Now I can access items in the entire class. 
}

>ChangeNotifierProxyProvider<Model1, Model2>(
//create the class to pass the value, which is M2. 
  create: (_) => Model2(Provider.of<Model1>(context)),
  update: (_, model1, model2) => model2..items
)



>Model2 model2 = Provider.of<Model2>(context, listen: false);
>>Text(model2.items),
于 2021-08-16T11:31:58.023 回答
0

我正在尝试实现相同的场景,这是我的代码:主文件:

        ChangeNotifierProvider<SharedPreferencesData>(
      create: (context) => SharedPreferencesData(),
    ),
    ChangeNotifierProxyProvider<SharedPreferencesData, DatabaseService>(
      create: (_) => DatabaseService(),
      update: (_, sharedPreferencesData, databaseService) {
        print('ChangeNotifierProxyProvider RAN');
        databaseService..setSpCompanyId = sharedPreferencesData.sPCompanyId;
        return null;
      },
    ),

SharedPreferencesData 文件:

    class SharedPreferencesData with ChangeNotifier {
    String sPCompanyId = '';
    void setCompanyId(String cpID) {
     sPCompanyId = cpID;
     print('setCompanyId sPCompanyId:$sPCompanyId');
     notifyListeners();
    }
  }

数据库服务文件:

class DatabaseService with ChangeNotifier {
  String sPCompanyId = 'empty';
  String get getSpCompanyId => sPCompanyId;

  set setSpCompanyId(String value) {
    print('value in setter database before if: $value');
    if (value != getSpCompanyId) {
      print('value in setter database: $value');
      sPCompanyId = value;
      notifyListeners();
    }
  }

DatabaseService 类不更新。我已经添加了打印来确定什么正在运行,什么没有运行。当我运行我的代码时,Shared_Preferences / setCompanyId 方法中的打印正确运行。然而 main.dart 文件中的打印功能 print('ChangeNotifierProxyProvider RAN'); 数据库服务文件中的 AND 打印('setter 数据库中的值:$value');不运行。

我错过了什么?为什么 SharedPreferencesData 中的 notify sPCompanyId setter notifyListeners() 没有通过 ChangeNotifierProxyProvider 更新 DatabaseService String sPCompanyId?谢谢!

于 2020-07-17T10:48:48.270 回答