Индикатор активности не отображается, пока не будет выполнен весь код

Обычно у меня есть индикатор активности, который не отображается до тех пор, пока не будет выполнен весь остальной код метода. Я посмотрел, и для свойства IsBusy устанавливается значение true как на стороне кода (страница входа), так и в привязке xaml (вход в систему xaml), поэтому я знаю, что правильное значение по крайней мере передается.

Я почти уверен, что у меня все настроено правильно, поскольку async / await ничего не блокирует.

У меня есть класс BaseViewModel, который используют все мои модели представления. Вот код для IsBusy:

bool isBusy = false;
    public bool IsBusy
    {
        get { return isBusy; }
        set { SetProperty(ref isBusy, value); }
    }

    protected bool SetProperty<T>(ref T backingStore, T value,
        [CallerMemberName]string propertyName = "",
        Action onChanged = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

Вот мой XAML для страницы входа. Индикатор активности размещается внутри единственного макета стека внутри тега страницы содержания:

<ActivityIndicator IsRunning="{Binding IsBusy}"
                     IsVisible="{Binding IsBusy}"
                      HeightRequest="40"
                      VerticalOptions="CenterAndExpand"
                      HorizontalOptions="CenterAndExpand">
        <ActivityIndicator.WidthRequest>
            <OnPlatform x:TypeArguments="x:Double" iOS="100" Android="100" />
        </ActivityIndicator.WidthRequest>
        <ActivityIndicator.Color>
            <OnPlatform x:TypeArguments="Color"
                  iOS="#2499CE" />
        </ActivityIndicator.Color>
    </ActivityIndicator>

А вот код LoginPageViewModel. Если я правильно понимаю, индикатор должен отображаться, как только он будет установлен в значение true в первой строке, а затем исчезнет после того, как вызов API будет выполнен, а пользователь не аутентифицирован.

public async void OnLogin()
    {
        IsBusy = true;

        var isAuthenticated = await LoginPageValidation.IsAuthenticated(email, password);
        if (!isAuthenticated )
        {
            IsBusy = false;
            IsForgotPasswordLabelVisible = true;
            DisplayUserAndPasswordMismatchPrompt();
            return;
        }
    }

Я уверен, что проблема в чем-то небольшом, но я этого просто не вижу.

РЕДАКТИРОВАТЬ: добавление методов IsAuthenticated

IsAuthenticated

public static async Task<bool> IsAuthenticated(string email, string password)
    {
        var isAuthenticated = false;
        try
        {
            var payload = $"{{\n\t\"Email\":\"{email}\",\n\t\"Password\":\"{password}\"\n}}";
            var response = await LoginApi.Authenticate(payload);
            isAuthenticated = bool.Parse(response["isAuthenticated"].ToString());
        }
        catch (Exception e)
        {
            // log stuff here
        }

        return isAuthenticated;
    }

Аутентифицировать вызов API:

public static async Task<JObject> Authenticate(string payloadBody)
    {
        IRestResponse response = null;
        try
        {
            var client = new RestClient($"{url}/authenticate");
            var request = new RestRequest(Method.POST);
            request.AddHeader("Content-Type", "application/json");
            request.AddParameter("undefined", payloadBody, ParameterType.RequestBody);
            response = client.Execute(request);
        } catch (Exception e)
        {
            // log some bad stuff here
        }

        return JObject.Parse(response.Content);
    }

person user1818298    schedule 29.12.2019    source источник
comment
поле isBusy является защищенным или частным?   -  person Lindsay    schedule 30.12.2019
comment
Не указано, поэтому я думаю, это внутреннее   -  person user1818298    schedule 30.12.2019
comment
Я думаю, что это делает его частным, хотя я не уверен, что это действительно будет причиной - stackoverflow.com/questions/2521459/.   -  person Lindsay    schedule 30.12.2019
comment
Я просто сделал его публичным, чтобы дважды проверить, и да, он все еще не появлялся после установки isBusy на true   -  person user1818298    schedule 30.12.2019
comment
Я тестирую аналогичный образец, который только заменяет ваш метод IsAuthenticated с задержкой, и он работает, не могли бы вы показать свой IsAuthenticated? или, если возможно, вы можете поделиться упрощенным примером   -  person Leo Zhu - MSFT    schedule 30.12.2019
comment
@ LeoZhu-MSFT обновлен кодом метода   -  person user1818298    schedule 30.12.2019
comment
@ user1818298, вы можете отлаживать эту строку, если (! isAuthenticated), посмотрите, войдет ли она в нее прямо сейчас после IsBusy = true;, когда вы вызываете метод OnLogin, если да, попробуйте использовать client.ExecuteAsync вместо client.Execute   -  person Leo Zhu - MSFT    schedule 30.12.2019
comment
@ LeoZhu-MSFT, думаю, ты прав. Я думаю, мне нужно выполнять async вместо выполнения. к сожалению, завтра мне придется поиграться с этим. Спасибо за помощь! Я обязательно прокомментирую обновления.   -  person user1818298    schedule 30.12.2019
comment
@ LeoZhu-MSFT, ты был прав. Мне пришлось перейти с client.Execute на client.ExecuteTaskAsync, и он работает как шарм. добавьте свой комментарий в качестве ответа и отметьте его.   -  person user1818298    schedule 31.12.2019
comment
@ user1818298 хорошо, я сделаю это   -  person Leo Zhu - MSFT    schedule 31.12.2019


Ответы (2)


С помощью обновленных кодов метода Authenticate вы можете изменить

 client.Execute;

to

 client.ExecuteAsync

в этом случае вы отобразите свой ActivityIndicator, как и ожидаете

person Leo Zhu - MSFT    schedule 31.12.2019

Убедитесь, что ваша модель просмотра реализует INotifyPropertyChanged, а затем:

    public bool IsBusy
    {
        set { isBusy = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsBusy))); }
        get { return isBusy; }
    }
person Adlorem    schedule 30.12.2019