在等待操作完成时显示 ProgressBar
Display ProgressBar while waiting for operation to complete
在我的 MVVMCross 应用程序中,我有一个 Android ProgressBar 定义为:
<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;
}
但是 ProgressBar 不会显示,除非我删除最后一个 IsBusy = false;
,
但这意味着仅在 Next() 方法退出时显示(而不是在等待时)
如何在等待时显示 ProgressBar 并在导航到下一页之前禁用它?
===编辑====
结束这样做:
public void Next()
{
async () =>
{
IsBusy = true;
await DoWork();
IsBusy = false;
});
}
将其余代码添加到 DoWork 并等待任务
//THE EXPENSIVE OPERATION
var response = await CallTimeConsumingServiceReturningTask();
发生这种情况是因为更新 UI 的过程当前发生在与您的昂贵操作相同的线程中。在您的操作完成之前,UI 线程会被阻塞并且视觉反馈永远不会正确显示。要解决这个问题,您需要将 CallTimeConsumingService()
变成一个异步调用(使其成为 return 一个 Task<T>
)并 await
以使其完成。
如果您的方法中有网络调用,则阻塞方法具有已经可以等待的异步对应方法。如果你的方法只涉及繁重的处理,你应该使用 TaskCompletionSource
or 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;
}
在我的 MVVMCross 应用程序中,我有一个 Android ProgressBar 定义为:
<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;
}
但是 ProgressBar 不会显示,除非我删除最后一个 IsBusy = false;
,
但这意味着仅在 Next() 方法退出时显示(而不是在等待时)
如何在等待时显示 ProgressBar 并在导航到下一页之前禁用它?
===编辑====
结束这样做:
public void Next()
{
async () =>
{
IsBusy = true;
await DoWork();
IsBusy = false;
});
}
将其余代码添加到 DoWork 并等待任务
//THE EXPENSIVE OPERATION
var response = await CallTimeConsumingServiceReturningTask();
发生这种情况是因为更新 UI 的过程当前发生在与您的昂贵操作相同的线程中。在您的操作完成之前,UI 线程会被阻塞并且视觉反馈永远不会正确显示。要解决这个问题,您需要将 CallTimeConsumingService()
变成一个异步调用(使其成为 return 一个 Task<T>
)并 await
以使其完成。
如果您的方法中有网络调用,则阻塞方法具有已经可以等待的异步对应方法。如果你的方法只涉及繁重的处理,你应该使用 TaskCompletionSource
or 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;
}