在我的应用程序中,我从REST API请求一个车辆集合,并将它们存储到一个属性中。这是使用异步任务完成的。我的页面使用绑定到这个可观察集合的选取器来使用它。目前,当页面加载时,根据使用速度的不同,选取器还没有填充。这通过等待一秒钟并重新打开选取器来解决它的问题。
我的假设是任务还没有完成,它运行异步意味着UI没有它继续运行。但是我不能肯定,因为我不知道如何在UI加载时测试它的值。
我想知道我可以采取什么措施来确保用户不会遇到这种类型的数据不加载。
简化视图模型
internal class BaseVehicleViewModel : BaseViewModel
{
public BaseVehicleViewModel()
{
Task.Run(async () => await GetAssets()).ConfigureAwait(false);
}
protected ObservableCollection<Asset> vehicles;
public ObservableCollection<Asset> Vehicles
{
get => vehicles;
set => SetProperty(ref vehicles, value);
}
protected async Task GetAssets()
{
var vehicles = await App.AppServiceClient.AssetsAsync();
if (vehicles != null)
{
Vehicles =
new ObservableCollection<Asset>(vehicles.Where(v => v.Active == 1));
}
}
简化视图
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App.Views.Page"
xmlns:vm="clr-namespace:App.ViewModels">
<ContentPage.BindingContext>
<vm:ViewModel />
</ContentPage.BindingContext>
<ContentPage.Content>
<Picker Title="Select a vehicle"
ItemsSource="{Binding Vehicles}"
ItemDisplayBinding="{Binding Reg}"
SelectedItem="{Binding SelectedVehicle, Mode=TwoWay}"/>
</ContentPage.Content>
</ContentPage>
2条答案
按热度按时间moiiocjp1#
我的假设是任务还没有完成,它运行异步意味着UI没有它就继续运行。
这是正确的代码当前执行加载作为一个即发即弃方法。即发即弃有几个问题:一个是不容易/不可能检测到它何时完成;另一个是(在这种情况下)忽略异常。
我想知道我可以采取什么措施来确保用户不会遇到这种类型的数据不加载。
用户总是会以某种方式体验数据加载,我建议你为你的页面设计一个“加载”状态。
我不建议阻塞异步工作。这将阻塞UI线程,提供非常糟糕的用户体验。用户只会看到一个非交互式的空白屏幕,操作系统会认为应用程序没有响应。如果这是一个移动的应用程序,那就更糟了,因为你只使用了一个应用程序就让整个屏幕都没有响应了;一些应用程序商店会自动测试这种行为,如果你的应用程序做了这种事情,就会拒绝它。
你需要设计用户体验来处理代码的异步特性,而不是阻塞或“发射后忘记”,这通常意味着同步地立即初始化到“加载”状态,然后用结果(或错误消息)更新用户界面。
我有一个old article,它提供了更多的细节,并建议一个类似于可绑定数据的
Task<T>
的类型,这个想法已经被复制到了几个库中:NotifyTask<T>
in Nito.Mvvm.Async,我最初的实现。MvxNotifyTask<TResult>
in MvvmCross .ObservableObject.TaskNotifier
in the .NET Community Toolkit / MVVM Toolkit v7 .NotifyTaskCompletion<T>
in the .NET Community Toolkit / MVVM Toolkit v6 .它们的一般用法都是相同的,只是API稍有不同。例如,使用
NotifyTask<T>
:现在,您的
Vehicles
是NotifyTask<ObservableCollection<Asset>>
而不是ObservableCollection<Asset>
,您的数据绑定代码可以绑定到Vehicles.Result
以绑定到ObservableCollection<Asset>
(在加载资源之前是null
),也可以绑定到Vehicles.IsNotCompleted
以显示微调器/ backbone 而不是完整的UI,如果加载失败,则绑定到Vehicles.ErrorMessage
,等等。w1e3prcc2#
首先,可以尝试让async方法同步运行,比如:
此外,还可以使用EventToCommand将Page的
OnAppearing
事件转换为视图模型中的命令。并且可以在ViewModel中声明一个flag来检查数据是否已经加载,比如:
最后,您可以参考有关when to load the ViewModel for asynchronous data in a Xamarin Android app.的案例