Flutter中ChangeNotifierProxyProvider更新时如何持久化子Provider状态?
问题:ChangeNotifierProxyProvider更新时丢失Job的career数据
现有Person和Job两个ChangeNotifier Provider,Job依赖Person。通过ChangeNotifierProxyProvider初始化后,在initState中设置Job的career为Accountant,初始可正常打印包含该值的title;但调用Person的increaseAge方法更新年龄后,Job的career恢复为默认值"na"。如何在Person更新时持久化Job的career数据?
相关代码
Person类
class Person with ChangeNotifier { Person({required this.name, required this.age}); final String name; int age; void increaseAge() { age++; notifyListeners(); } }
Job类
class Job with ChangeNotifier { Job(this.person); String career = "na"; addCareer(value) { career = value; notifyListeners(); } final Person person; String get title { return '${person.name}, $career, ${person.age}'; } }
初始化代码
void main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider<Person>(create: (_) => Person(name: 'John', age: 25)), ChangeNotifierProxyProvider<Person, Job>( create: (BuildContext context) => Job(Provider.of<Person>(context, listen: false)), update: (BuildContext context, Person person, Job? job) => Job(person), ), ], child: const MyApp(), ), ); }
initState代码
@override void initState() { super.initState(); final job = Provider.of<Job>(context, listen: false); job.addCareer("Accountant"); }
解决方案
问题根源在于ChangeNotifierProxyProvider的update方法每次都新建Job实例,新实例的career会重置为默认值"na",覆盖之前设置的值。要解决这个问题,需要复用已有的Job实例,仅更新其中依赖的Person引用,保留原有的career数据。
步骤1:修改Job类,支持更新Person引用
将Job类中final Person person改为可更新的私有变量,并添加更新方法:
class Job with ChangeNotifier { Job(this._person); String career = "na"; Person _person; // 更新Person引用的方法 void updatePerson(Person newPerson) { _person = newPerson; notifyListeners(); } void addCareer(String value) { career = value; notifyListeners(); } // 对外暴露person的 getter Person get person => _person; String get title { return '${_person.name}, $career, ${_person.age}'; } }
步骤2:修改ChangeNotifierProxyProvider的update逻辑
不再新建Job实例,而是复用现有实例并更新Person引用:
void main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider<Person>(create: (_) => Person(name: 'John', age: 25)), ChangeNotifierProxyProvider<Person, Job>( create: (context) => Job(Provider.of<Person>(context, listen: false)), update: (context, person, job) { // 复用已有的Job实例,仅更新Person引用 job?.updatePerson(person); // 首次创建时返回新实例,后续返回复用的实例 return job ?? Job(person); }, ), ], child: const MyApp(), ), ); }
原理说明
当Person更新并调用notifyListeners()时,ChangeNotifierProxyProvider会触发update方法。此时我们不再创建新的Job实例,而是对已有的Job实例仅更新其Person引用,保留之前通过addCareer设置的career值,从而实现数据持久化。
内容的提问来源于stack exchange,提问作者s-hunter
相关产品推荐
相关产品推荐

