ChangeNotifierProvider无法更新模型问题求助
问题解决方案
核心问题分析
- 重复注册回调:在
build方法中注册AzureB2C回调,每次Widget重建都会新增回调实例,导致逻辑冲突或执行异常。 - Provider.of使用错误:在异步方法中使用
listen: true调用Provider.of,该参数要求必须在Widget的build周期内使用,非build周期调用会引发静默失败。 - 冗余回调代码:多处注册相同的
POLICY_TRIGGER_INTERACTIVE回调,导致逻辑重复。
分步修复方案
1. 将回调注册移至initState
把AzureB2C的回调注册代码从build方法移到initState,确保仅注册一次:
class LoginState extends State<Login> { B2CConfiguration? _configuration; @override void initState() { super.initState(); // 仅在初始化时注册回调 AzureB2C.registerCallback(B2COperationSource.INIT, (result) async { if (result.reason == B2COperationState.SUCCESS) { _configuration = await AzureB2C.getConfiguration(); if (!mounted) return; await checkLogin(context); } }); AzureB2C.registerCallback(B2COperationSource.POLICY_TRIGGER_INTERACTIVE, (result) async { if (result.reason == B2COperationState.SUCCESS) { if (!mounted) return; await checkLogin(context); } }); AzureB2C.handleRedirectFuture().then((_) => AzureB2C.init("auth_config")); } // ... 其他代码 }
2. 修改Provider.of的listen参数
在checkLogin方法中,将listen设为false——我们仅需要获取LoginModel实例来更新状态,不需要监听状态变化:
checkLogin(BuildContext context) async { List<String>? subjects = await AzureB2C.getSubjects(); if (subjects != null && subjects.isNotEmpty) { B2CAccessToken? token = await AzureB2C.getAccessToken(subjects[0]); if (!mounted || token == null) return; final encodedData = token.token.split('.')[1]; final data = utf8.fuse(base64).decode(base64.normalize(encodedData)); final claims = Claims.fromJson(jsonDecode(data)); // 使用listen: false获取实例 var m = Provider.of<LoginModel>(context, listen: false); m.logIn(claims); } }
3. 删除冗余回调代码
移除你最初编写的独立POLICY_TRIGGER_INTERACTIVE回调代码,避免与LoginWidget内的回调重复触发。
额外注意事项
- 始终在异步操作完成后检查
mounted状态,避免使用已销毁的Widget上下文。 - 若需要在UI中监听
LoginModel的状态变化,使用Consumer或Selector组件,而非直接在业务逻辑中用listen: true。
内容的提问来源于stack exchange,提问作者Emaborsa
相关产品推荐
相关产品推荐

