.NET MAUI中签到操作时ActivityIndicator不显示问题的解决方法
核心问题分析
OnConfirmClicked中设置IsBusy=true后,finally块会立刻执行IsBusy=false——因为Dispatcher.Dispatch的异步委托未被等待,主线程还没来得及渲染加载指示器,就被重置了状态。AcceptFunction使用async void声明,无法被外部等待,导致异步流程失控,进一步加剧了IsBusy被提前关闭的问题。- 多处重复设置
IsBusy=false,逻辑混乱,导致加载状态无法持续到API调用完成。
解决方案
1. 修正OnConfirmClicked方法,改为异步并等待操作完成
将方法改为async void(事件处理程序专属声明),移除多余的Dispatcher.Dispatch嵌套,确保IsBusy在所有异步操作完成后才被重置:
private async void OnConfirmClicked(object sender, EventArgs e) { Close(); eventCalendarViewModel._openPopup = null; eventCalendarViewModel.IsBusy = true; try { if (Support.reservationOnlyOwnGym) { if (selectedLocation.code == Support.userLocation.code) { await AcceptFunction(sender, e, appointment); } else { await Application.Current.MainPage.DisplayAlert(Languages.Oops, Languages.Only_able_to_check_in_and_reserve_your_home_center, "OK"); } } else { await AcceptFunction(sender, e, appointment); } } finally { eventCalendarViewModel.IsBusy = false; } }
2. 重构AcceptFunction为async Task,移除不必要的调度
普通异步方法改用async Task以便被等待,同时去掉嵌套的Dispatcher.Dispatch(await后会自动回到UI上下文,无需手动调度):
async Task AcceptFunction(object sender, EventArgs e, AppointmentInfo info) { var locationToCheck = Support.LocationRows.Where(l => l.code == info.Location).First(); bool isArrived = false; double distanceinmeters = await PointDistance(locationToCheck); if (distanceinmeters > -1 && distanceinmeters < maxDistance) { // 注意:原代码此处传的是字符串"info.Location",修正为变量info.Location ObservableCollection<CustomerArrivedInfo> arrived = await RestApiClient.PutArrived(Support.SessionID, info.Location, 1); if (arrived != null && arrived[0].status) { isArrived = true; Close(); await Task.Delay(200); await Application.Current.MainPage.DisplayAlert(info.Detail, Languages.Check_in_succesfull, "OK"); await eventCalendarViewModel.CalendarUpdate(); } else { await Task.Delay(200); await Application.Current.MainPage.DisplayAlert(info.Detail, Languages.Check_in_failed, "OK"); } } else { await Task.Delay(600); await Application.Current.MainPage.DisplayAlert(info.Detail, Languages.Check_in_failed_too_far_away_from_center, "OK"); await eventCalendarViewModel.CalendarUpdate(); if (!isArrived && Support.enableBTScan) { BluetoothScan.ResetPermissionRefused(); BluetoothScan.Scan(); } } }
3. 额外优化点
- 确保加载指示器的Grid布局在页面最上层(比如放在Grid的最后一行,或使用绝对布局覆盖所有内容),避免被其他控件遮挡。
- 检查
PointDistance方法是否为真正的异步实现,避免阻塞UI线程。
内容的提问来源于stack exchange,提问作者Ayesh Nipun
相关产品推荐
相关产品推荐

