0

В моей MVVMCross App У меня есть Android ProgressBar определяется как:Дисплей 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 во время ожидания и отключения его перед переходом на следующую страницу?

=== EDIT ====

Закончилось это сделать:

public void Next() 
{ 
    async() => 
     { 
      IsBusy = true; 
      await DoWork(); 
      IsBusy = false; 
     }); 
} 

добавляя остальную часть кода в DoWork с AWAIT для выполнения этой задачи

//THE EXPENSIVE OPERATION 
var response = await CallTimeConsumingServiceReturningTask(); 

ответ

2

Этот происходит потому, что процесс обновления пользовательского интерфейса в настоящее время происходит в том же потоке, что и ваша дорогостоящая операция. Пока ваша операция не завершится, поток пользовательского интерфейса заблокирован, и визуальная обратная связь никогда не отображается должным образом. Чтобы решить эту проблему, вам необходимо сделать свой CallTimeConsumingService() асинхронным вызовом (чтобы он возвращал Task<T>) и await для его завершения.

Если у вас есть сетевые вызовы в вашем методе, методы блокировки имеют аналоги Async, которые уже ожидаются. Если ваш метод просто требует интенсивной обработки, вы должны использовать TaskCompletionSource или Task.Run.

1

Предыдущий ответ правильный, но вы можете написать чистый код, делая следующий() метод асинхр:

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; 
} 
+0

Согласитесь, закончилось это делать, когда было время, когда требуется немного рефакторинга. – Riga