在以下 Flutter 代码中,
ValueListenableBuilder
用于在 ValueNotifier
发生变化时显示对话框。但是,当再次设置相同的值时,不会触发该对话框。
ValueNotifier 仅在值发生变化时通知侦听器。目标是即使多次设置相同的值(true)也能触发对话框。
即使再次为 adWatchNeeded 设置相同的值(true),如何触发对话框?
让我们假设一个简单的视图模型类,如下所示,或者简单地尝试一下here
重要提示:不需要像 bloc、riverpod 等状态管理解决方案。
This is just for experimental purpose
class FeatureViewModel extends ChangeNotifier {
ValueNotifier<bool> adWatchNeeded = ValueNotifier(false);
void useFeature() {
// Some API calls..
// Unfortunately user must watch ads to use feature..
adWatchNeeded.value = true;
}
}
然后在UI端使用
Widget _buildAdWatchNeededDialog() {
return ValueListenableBuilder<bool>(
valueListenable: _viewModel.adWatchNeeded,
builder: (context, adWatchNeeded, child) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (adWatchNeeded) {
showAdWatchNeededDiaog(context);
}
});
return const SizedBox.shrink();
},
);
}
然后在树上使用它
class SomeFeatureWidget extends StatefulWidget {
const SomeFeatureWidget({Key? key}) : super(key: key);
@override
State<SomeFeatureWidget> createState() => _SomeFeatureWidgetState();
}
class _SomeFeatureWidgetState extends State<SomeFeatureWidget> {
final _viewModel = FeatureViewModel();
@override
Widget build(BuildContext context) {
return Column(
children: [
_buildFeatureUsageDialog(),
_buildAdWatchNeededDialog(),
],
);
}
Widget _buildFeatureUsageDialog() {
return TextButton(onPressed: () => _viewModel.useFeature(), child: const Text('Use Feature'));
}
Widget _buildAdWatchNeededDialog() {
return ValueListenableBuilder<bool>(
valueListenable: _viewModel.adWatchNeeded,
builder: (context, adWatchNeeded, child) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (adWatchNeeded) {
showAdWatchNeededDiaog(context);
}
});
return const SizedBox.shrink();
},
);
}
void showAdWatchNeededDiaog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: const Text('Wath ads to use this feature'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Watch Ad')),
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('No, thanks'))
],
);
},
);
}
}
ValueNotifier 仅在值发生变化时通知侦听器。目标是即使多次设置相同的值(true)也能触发对话框。
根据定义,这就是它应该如何工作。 如果即使值相同也需要事件,请考虑使用 Stream 的事件,或在值中包含微秒时间戳。