我正在尝试找到一些如何在现实世界场景中使用Xamarin.Forms,ReactiveUI和Akavache的'最佳实践'示例。 假设有一个简单的页面代表客户详细信息。它应该在激活(导航到)时从服务器检索数据。我喜欢Akavache的GetAndFetchLate扩展方法的想法,所以我想使用它。
我最终得到了这样的东西:
public class CustomerDetailViewModel : ViewModelBase //(ReactiveObject, ISupportsActivation)
{
private readonly IWebApiClient webApiClient;
public Customer Customer { get; }
public ReactiveCommand<Unit, Unit> GetDataCommand { get; }
public CustomerDetailViewModel(Customer customer, IWebApiClient webApiClient = null)
{
this.Customer = customer;
this.webApiClient = webApiClient ?? Locator.Current.GetService<IWebApiClient>();
GetDataCommand = ReactiveCommand.CreateFromTask(GetData);
}
private Task GetData()
{
BlobCache.LocalMachine.GetAndFetchLatest($"customer_{Customer.Id.ToString()}",
() => webApiClient.GetCustomerDetail(Customer.Id))
.Subscribe(data =>
{
CustomerDetail = data;
});
return Task.CompletedTask;
}
private CustomerDetail customerDetail;
public CustomerDetail CustomerDetail
{
get => customerDetail;
set => this.RaiseAndSetIfChanged(ref customerDetail, value);
}
}
DTO
public class Customer
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class CustomerDetail
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
视图绑定
this.WhenActivated(disposables =>
{
this.OneWayBind(this.ViewModel, x => x.Customer.Name, x => x.nameLabel.Text)
.DisposeWith(disposables);
this.OneWayBind(this.ViewModel, x => x.CustomerDetail.Description, x => x.descriptionLabel.Text)
.DisposeWith(disposables);
this.ViewModel?.GetDataCommand.Execute().Subscribe();
}
但我认为这不是 100% 防弹的。这有一些可能的问题:
- 当我想在激活时加载数据时,是否可以在视图上
this.WhenActivated(d => ...)
调用this.ViewModel?.GetDataCommand.Execute().Subscribe();
? - 绑定到
CustomerDetail.Description
会导致NullReferenceException
我说得对吗?还是安全? - 我想做一些类似的事情:"如果有
CustomerDetail
,请展示CustomerDetail.Name
。当尚未加载时,显示Customer.Name
"。因此,我需要在视图模型上创建特定的属性吗? - 如何指示装载?
- 我在这里错过了一些重要的东西吗?我可能遇到的其他问题吗?
您可以在
- ViewModel中使用WhenActive,您可以在
ISupportActivation
实现一个接口。然后,您可以从 ViewModel 调用或运行GetData
。还有一个名为InvokeCommand()
的帮助程序扩展方法 - 我们故意不向下传播。我们使用自己的零传播形式。 在这种情况下
- ,您可能会在控件上设置文本是一种方式。在显示您的视图之前,不会发生"何时激活"。
- 我通常将其作为视图模型上的布尔属性来完成,视图模型可以考虑不同的命令等。您可能会对调用
StartsWith(false)
的命令执行ObservableAsPropertyHelper
- 我可能会在您的 BlobCache 上使用
ObservableAsPropertyHelper
,但看起来代码合理。