Flutter Provider:拆分通知的正确方法
Posted
技术标签:
【中文标题】Flutter Provider:拆分通知的正确方法【英文标题】:Flutter Provider: proper way to split notifying 【发布时间】:2021-01-04 20:34:51 【问题描述】:我正在尝试使用Provider
拆分小部件的触发更新。
我正在使用最新的Flutter
版本。在应用程序中,我还使用context.select()
、context.watch()
和context.read()
。
现在主要目标。我到底在说什么。所以我有一些通知:
class ExpenseNotifier with ChangeNotifier
List<Category> _selectedCategories = [];
Expense _currentExpense;
int _removeId;
Expense _editExpense;
现在,ExpenseNotifier
有几个消费者。当某些事情发生变化时,所有消费者都会更新。除了一种情况:当_editExpense
更新时,只有一个消费者应该被更新。问题是 Expense
类已经存在于通知程序中,因此所有连接到 _currentExpense
的消费者也会对 _editExpense
更新做出反应...
我现在正在使用选择器。像这样:
context.select<ExpenseNotifier, Expense>((notifier) => notifier.currentExpense);
但由于某种原因,小部件似乎也会对 _editExpense
更新做出反应...
这种情况的正确解决方案是什么?是否有可能(不定义新类型)在ExpenseNotifier
内实现它?
也许,这样的事情应该可以工作:
class EditExpense
final Expense expense;
EditExpense(this.expense);
所以在这种情况下需要包装类。如果我错了,请纠正我
【问题讨论】:
可能最简单的解决方案是让一些消费者忽略 editExpense 字段 【参考方案1】:我发现你的问题很有趣,所以我认为值得研究一下。我给出了一种一般性的答案,但我认为你会从中受益。
首先向数据类添加方法,只更新必填字段, 像这样:
class DataClass with ChangeNotifier
String firstString = " ";
String secondString = " ";
void updateFirst(String newString)
firstString = newString;
notifyListeners();
void updateSecond(String newString)
secondString = newString;
notifyListeners();
现在是重构的时候了,你必须创建两个拥有自己构建方法的类(或方法)(你也可以定义两个方法并将BuildContext
传递给它们):
class StringOne extends StatelessWidget
@override
Widget build(BuildContext context)
print("StringOne build method is called");
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Column(
children: [
Text(context.select((DataClass value) => value.firstString)),
Container(
height: 100,
width: 100,
child: TextField(
onChanged: (text)
context.read<DataClass>().updateFirst(text);
,
),
)
],
)
],
);
和
class StringTwo extends StatelessWidget
@override
Widget build(BuildContext context)
print("StringTwo build method is called");
return Column(
children: <Widget>[
Column(
children: [
Text(context.select((DataClass value) => value.secondString)),
Container(
height: 100,
width: 100,
child: TextField(
onChanged: (text)
context.read<DataClass>().updateSecond(text);
,
),
),
],
)
],
);
最后在描述 UI 的其他类中有这些类:
class ProviderExample extends StatelessWidget
@override
Widget build(BuildContext context)
return ListView(
children: [StringOne(), StringTwo()],
);
您可能会说它会增加冗长,实际上,重构通常会使代码更冗长,但它也使代码更清晰且易于维护。在您的情况下,它还可以防止不必要的构建。
Console :
I/flutter ( 1469): StringTwo build method is called
I/flutter ( 1469): StringTwo build method is called
I/flutter ( 1469): StringTwo build method is called
I/flutter ( 1469): StringTwo build method is called
I/zygote64( 1469): Increasing code cache capacity to 1024KB
I/flutter ( 1469): StringOne build method is called
I/chatty ( 1469): uid=10140(com.example.stack_overflow) 1.ui identical 7 lines
I/flutter ( 1469): StringOne build method is called
I/flutter ( 1469): StringOne build method is called
【讨论】:
您好,感谢您的回复! :) 我想我有这样的东西,对我来说这是行不通的。意味着两个小部件都更新了 好吧,如果你做过类似的事情,那么一次只能调用一个构建。如果您分享更多代码,可能会对您有所帮助。以上是关于Flutter Provider:拆分通知的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Flutter 中使用 Provider 显示来自 ChangeNotifier 的错误
如何在 Flutter 中使用 Provider 正确获取 API
导航到不同路线后,Flutter 找不到正确的 Provider<Bloc>