Flutter中用Provider更新状态后UI没刷新怎么办?
我在用Provider做状态管理,调用了notifyListeners(),但界面上的数据没变,还是旧的。明明数据已经改了,为啥UI不重建呢?
我试过把Consumer包在外层Widget上,也确认过context没拿错,但就是不生效。是不是哪里写错了?
class CounterModel extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // 这里调用了,但UI没反应
}
}
常见坑有几个:
第一个是 Consumer 里用的 count 是不是直接从 model 里读的?比如你是不是这么写的:
Consumer
builder: (context, model, child) {
return Text(model.count.toString());
},
)
如果是这样那就没问题。但如果你是这么写的:
Consumer
builder: (context, model, child) {
var c = model.count; // 这句本身没问题
return Text(c.toString());
},
)
也没问题……等等,先别急,继续看。
真正容易踩的点是:你是不是在别的地方直接改了 _count,而不是走 increment()?比如你 somewhere 里写了 counterModel._count++,那当然不会触发 rebuild,因为没调 notifyListeners。
另一个可能是你用的是 Consumer 的旧版本写法,或者用了 ChangeNotifierProvider 的 value 构造方式,但没传对 model 实例。比如:
ChangeNotifierProvider.value(
value: myCounterModel,
child: MyApp(),
)
这种写法没问题,但如果你在某个子 widget 里又 new 了一个 CounterModel,然后调它的 increment,UI 当然不刷新——你改的是另一个实例。
还有个隐蔽的坑是:Consumer 外面包了不相关的父 widget(比如 StatefulWidget),而那个 widget 没重建,Consumer 也没触发 rebuild。可以试试把 Consumer 往上挪,包在最外层试试。
另外,你确认下 build 方法里是不是真的读了 count?比如你写成:
Text('$_count')
而 _count 是本地变量,没从 model 读——这种情况 UI 当然不更新。
最后,如果以上都没问题,可以加个打印验证下:
void increment() {
_count++;
print('count changed to $_count');
notifyListeners();
}
然后点按钮看控制台有没有打印。如果打印了但 UI 没变,那基本就是 UI 监听方式的问题;如果没打印,说明 increment 根本没被调到。
后端处理里经常遇到类似问题:数据改了但没通知监听者,Flutter 这边其实也一样,只是监听者换成了 Consumer。核心就是三点:改值走 setter / method、notifyListeners 必须调、UI 必须通过 Consumer 或其他方式订阅。
你贴一下你 UI 那边的 Consumer 写法,我帮你再看看是哪块漏了。