Этот шаблон подходит для загрузки и кэширования данных Akavache в ViewModel и привязки их к пользовательскому интерфейсу в Xamarin.Forms? - PullRequest
0 голосов
/ 09 апреля 2019

Я пытаюсь найти пример «наилучшей практики» по использованию Xamarin.Forms, ReactiveUI и Akavache в сценарии реального мира.Допустим, есть простая страница, представляющая детали клиента.Он должен извлекать данные с сервера при активации (навигация к).Мне нравится идея метода расширения GetAndFetchLatest от Akavache, поэтому я хотел бы использовать его.

В итоге я получил что-то вроде этого:

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);
  }
}

DTOs

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% пуленепробиваемое.Возможны следующие проблемы:

  1. Можно ли вызвать this.ViewModel?.GetDataCommand.Execute().Subscribe(); в this.WhenActivated(d => ...) в представлении, когда я хочу загрузить данные при активации?
  2. Привязка к CustomerDetail.Description может вызвать NullReferenceException Я прав?Или это безопасно?
  3. Я хочу сделать что-то вроде: «Если есть CustomerDetail, покажите CustomerDetail.Name. Когда он еще не загружен, покажите Customer.Name».Нужно ли из-за этого создавать определенное свойство в ViewModel?
  4. Как указать загрузку?
  5. Я что-то упустил здесь?У меня могут быть другие проблемы с этим?

1 Ответ

0 голосов
/ 13 апреля 2019
  1. Вы можете использовать WhenActivation в ViewModel, есть интерфейс, который вы можете реализовать ISupportActivation.Затем вы можете вызвать или запустить GetData из вашей ViewModel.Существует также вспомогательный метод расширения, называемый InvokeCommand()
  2. . Мы сознательно не распространяемся вниз.Мы используем нашу собственную форму нулевого распространения.
  3. Вы могли бы потенциально установить текст на вашем элементе управления в этом случае, это один из способов.WhenActivation не произойдет до тех пор, пока не будет отображено ваше представление.
  4. Обычно я делаю это как логическое свойство ViewModel, ViewModel может учитывать различные команды и т. Д. Вы можете потенциально сделать ObservableAsPropertyHelper длякоманда, вызывающая StartsWith(false)
  5. Потенциально я бы использовал ObservableAsPropertyHelper на вашем BlobCache, но выглядит разумным кодом.
...