在我的MVVMCross应用程序中,我有一个Android进度条定义为:
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:progressDrawable="@drawable/circular_progress_bar"
android:gravity="right"
local:MvxBind="Visibility Visibility(IsBusy)" />
在 ViewModel 中,单击按钮启动操作时执行的代码如下所示:
public void Next()
{
IsBusy = true;
try
{
//THE EXPENSIVE OPERATION
var response = CallTimeConsumingService();
if (response.MethodFailed)
{
_dialogService.DisplayAlert(this, response.Message);
return;
}
ShowViewModel<ShowNextView>();
}
catch (Exception ex)
{
_dialogService.DisplayAlert(this, ex.Message);
}
IsBusy = false;
}
但是除非我删除最后一个IsBusy = false;
,否则进度条不会显示,但这意味着仅在 Next() 方法退出时显示(而不是在等待时)
在等待时显示进度条并在导航到下一页之前禁用它,我可以做些什么?
===编辑====
结束这样做:
public void Next()
{
async () =>
{
IsBusy = true;
await DoWork();
IsBusy = false;
});
}
将其余代码添加到 DoWork 中
,等待任务//THE EXPENSIVE OPERATION
var response = await CallTimeConsumingServiceReturningTask();
是因为更新 UI 的过程当前与昂贵的操作发生在同一线程中。在操作完成之前,UI 线程将被阻止,并且视觉反馈永远不会正确显示。要解决此问题,您需要将CallTimeConsumingService()
变成异步调用(使其返回Task<T>
)并await
以使其完成。
如果方法中有网络调用,则阻止方法具有已等待的异步对应项。如果您的方法只涉及繁重的处理,则应使用 TaskCompletionSource
或 Task.Run
。
前面的答案是正确的,但是您可以通过使next()方法异步来编写更干净的代码:
public async Task Next()
{
IsBusy = true;
try
{
//THE EXPENSIVE OPERATION
var response = await CallTimeConsumingServiceReturningTask();
if (response.MethodFailed)
{
_dialogService.DisplayAlert(this, response.Message);
return;
}
ShowViewModel<ShowNextView>();
}
catch (Exception ex)
{
_dialogService.DisplayAlert(this, ex.Message);
}
IsBusy = false;
}