基于Popup插件的DialogsService回调结果获取实现是否正确?
问题:弹窗服务的回调结果返回逻辑是否正确?
我正在使用一款弹窗页面插件,原有使用代码如下:
var confirm = new AlertDialog(new AlertSettings() { Title = "Confim Title", Message = "Confirm Question?"}); confirm.Callback += (result) => { if (result) { // do something } }; await PopupNavigation.PushAsync(confirm);
我尝试编写一个服务以获取bool类型的回调结果,相关代码如下:
public interface IDialogsService { Task<bool> DisplayConfirmAsync(string title, string message); } public class DialogsService : IDialogsService { public DialogsService() { } public async Task<bool> DisplayConfirmAsync(string title, string message) { bool tresult = false; var confirm = new AlertDialog(new AlertSettings() { Title = title, Message = message}); confirm.Callback += (result) => { tresult = (bool)result; }; await PopupNavigation.Instance.PushAsync(confirm); return tresult; } }
调用方式为:
bool result = await DialogsService.DisplayConfirmAsync("Confim Title", "Confirm Question?");
请问上述实现方式是否正确?
回答
你的实现不正确,核心问题在于 PopupNavigation.PushAsync 的行为:它只是将弹窗推入导航栈并完成显示动作,并不会等待用户完成交互(点击确认/取消按钮)就继续执行后续代码。因此你返回的 tresult 始终是初始化的 false,根本无法拿到用户的真实选择结果。
问题根源拆解
当你执行 await PopupNavigation.Instance.PushAsync(confirm); 时,await 仅等待弹窗完成"推入导航栈并显示"这个操作,而不是等待用户关闭弹窗。代码会立刻跳到 return tresult; 这一行,此时用户还未触发任何按钮点击,Callback 委托完全没被执行,tresult 自然还是初始值。
正确实现方式
我们可以用 TaskCompletionSource<bool> 来创建一个可手动完成的任务,等待弹窗的回调触发后再返回结果:
public class DialogsService : IDialogsService { public async Task<bool> DisplayConfirmAsync(string title, string message) { // 创建TaskCompletionSource,用于等待用户交互结果 var taskCompletionSource = new TaskCompletionSource<bool>(); var confirm = new AlertDialog(new AlertSettings() { Title = title, Message = message}); confirm.Callback += (result) => { // 用户做出选择后,设置任务的结果 taskCompletionSource.SetResult((bool)result); // 根据插件特性,可能需要手动关闭弹窗(若插件不自动处理) _ = PopupNavigation.Instance.PopAsync(); }; await PopupNavigation.Instance.PushAsync(confirm); // 等待用户的选择结果完成后再返回 return await taskCompletionSource.Task; } }
额外注意事项
- 关闭弹窗:部分弹窗插件在用户点击按钮后会自动关闭弹窗,如果你的插件没有这个特性,一定要在回调里调用
PopupNavigation.Instance.PopAsync(),否则弹窗会一直停留在界面上。 - 调用方式修正:你原来的调用代码
DialogsService.DisplayConfirmAsync是静态调用,但你的DisplayConfirmAsync是实例方法,实际使用时需要先实例化DialogsService(或通过依赖注入获取实例):// 示例:实例化服务后调用 var dialogsService = new DialogsService(); bool result = await dialogsService.DisplayConfirmAsync("Confirm Title", "Confirm Question?");
内容的提问来源于stack exchange,提问作者Kerberos
相关产品推荐
相关产品推荐

