Это правильный способ иметь кнопку, которая повторяет вызов API в приложении Android? - PullRequest
1 голос
/ 30 апреля 2019

Проект, над которым я работаю, получает список пользователей из API без комнаты в середине (только сетевая архитектура).На самом деле у меня есть код, работающий так, как я хочу, чтобы он работал, но мне интересно, является ли это правильным способом сделать это.Ниже я отмечаю, где именно у меня есть сомнения.

Мой пользовательский интерфейс - это RecyclerView, поддерживаемый ListAdapter.У меня есть ViewModel (mainViewModel), который наблюдает за списком пользователей, предоставляемых классом Repository, а также логическим значением, чтобы показать или нет кнопку «Повторить попытку».

В MainActivity.java у меня есть

// Observing the boolean that represents if the api call failed
mainViewModel.getCallFailure().observe(this, new Observer<Boolean>() {
    @Override
    public void onChanged(Boolean aBoolean) {
        if (aBoolean) {
            tryAgainButton.setVisibility(View.VISIBLE);
        } else {
            tryAgainButton.setVisibility(View.GONE);
        }
    }
});

// Setting up onClickListener
tryAgainButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mainViewModel.retryCall(); // HERE IS WHERE I'M HAVING DOUBTS
    }
});

MainViewModel.java имеет

public class MainViewModel extends ViewModel {

    ...

    public LiveData<Boolean> getCallFailure(){
        return userRepo.getCallFailure();
    }

    // THIS IS THE METHOD I'M CALLING FROM THE UI
    public void retryCall(){
        userRepo.getRetryCallback();
    }
}

И, наконец, Repository.java

public class Repository {
    private Call<UsersResponse> retryCall;
    private Callback<UsersResponse> callback;
    private final MutableLiveData<Boolean> callFailure = new MutableLiveData<>();

    public LiveData<List<UserModel>> getListUsers(){
        final MutableLiveData<List<UserModel>> users = new MutableLiveData<>();
        callFailure.setValue(false);

        (Api.getClient().getUsersList()).enqueue(new Callback<UsersResponse>() {
            @Override
            public void onResponse(Call<UsersResponse> call, Response<UsersResponse> response) {
                users.setValue(response.body().getUsersList());
                callFailure.setValue(false);
            }

            @Override
            public void onFailure(Call<UsersResponse> call, Throwable t) {
                Log.d("Response GET", t.toString());
                callFailure.setValue(true);
                setCallback(this);
                retryCall = call.clone();
            }
        });

        return users;
    }

    private void setCallback(Callback<UsersResponse> usersResponseCallback) {
        callback = usersResponseCallback;
    }

    public LiveData<Boolean> getCallFailure(){
        return callFailure;
    }

    public void getRetryCallback(){
        retryCall.enqueue(callback);
    }
}

Я попытался упомянуть только тот код, который мне кажется уместнымЯ управляю ProgressDialog так же, как и с логическим значением callFailure в репозитории, и оно творит чудеса.Но, честно говоря, что-то не так с вызовом mainViewModel.retryCall(); в файле MainActivity.java, я действительно буду признателен за любые предложения!

1 Ответ

0 голосов
/ 30 апреля 2019

В проектах, которые я сделал с использованием MVVM, мои действия и фрагменты уведомляют мою ViewModel так, как вы ее выставляете (вызывая метод, который действует как триггер), и наблюдайте за результатом через LiveData.

Одна вещь, которая для меня страннав том, что ваш репозиторий хранит часть состояния (повтор и сбой).В моих проектах я поместил эту логику во ViewModel, и мои репозитории находятся здесь для выполнения простых операций (например, сетевой вызов).Но это скорее личный выбор, чем все остальное.


РЕДАКТИРОВАТЬ : вот как я бы сделал это на основе вашего кода (возможно, существует лучший способ).

По сути, я предпочитаю управлять объектами LiveData в ViewModel, а не в репозитории, потому что, на мой взгляд, уровень репозитория является просто мостом между приложением и данными (в сети или в БД),и состояние пользовательского интерфейса (например, видимость кнопки повтора) должно управляться ViewModel.

Repository.java:

public class Repository {
    public void getListUsers(Callback<UserResponse> callback) {
        (Api.getClient().getUsersList()).enqueue(callback);
    }
}

MainViewModel.java:

public class MainViewModel extends ViewModel {

    ...

    private final MutableLiveData<Boolean> callFailure = new MutableLiveData<>();
    private final MutableLiveData<List<UserModel>> users = new MutableLiveData<>();

    public LiveData<Boolean> getCallFailure() {
        return callFailure;
    }

    public LiveData<Boolean> getUsers() {
        return users;
    }

    // THIS IS THE METHOD I'M CALLING FROM THE UI
    public void retryGetUsers() {
        callFailure.setValue(false);
        getUsers();
    }

    private void getUsers() {
        userRepo.getListUsers(new Callback<UserResponse>(){
            @Override
            public void onResponse(Call<UsersResponse> call, Response<UsersResponse> response) {
                users.setValue(response.body().getUserList());
            }

            @Override
            public void onFailure(Call<UsersResponse> call, Throwable t) {
                callFailure.setValue(true);
            }
        });
    }
}
...