value - single source of truth android




Como atualizar o LiveData de um ViewModel do serviço em segundo plano e da atualização da interface do usuário (4)

... na função loadUsers () estou buscando os dados de forma assíncrona ... Se eu iniciar um serviço para chamar a API do método loadUsers (), como posso atualizar a variável MutableLiveData> users desse serviço?

Se o aplicativo estiver buscando dados do usuário em um thread de segundo plano, postValue (em vez de setValue ) será útil.

No método loadData, há uma referência ao objeto "usuários" do MutableLiveData. O método loadData também busca alguns dados novos do usuário de algum lugar (por exemplo, um repositório).

Agora, se a execução estiver em um thread de segundo plano, o MutableLiveData.postValue () atualiza os observadores externos do objeto MutableLiveData.

Talvez algo assim:

private MutableLiveData<List<User>> users;

.
.
.

private void loadUsers() {
    // do async operation to fetch users
    ExecutorService service =  Executors.newSingleThreadExecutor();
    service.submit(new Runnable() {
        @Override
        public void run() {
            // on background thread, obtain a fresh list of users
            List<String> freshUserList = aRepositorySomewhere.getUsers();

            // now that you have the fresh user data in freshUserList, 
            // make it available to outside observers of the "users" 
            // MutableLiveData object
            users.postValue(freshUserList);        
        }
    });

}

Recentemente estou explorando a arquitetura Android, que foi introduzida recentemente pelo google. Da Documentation eu encontrei isto:

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<Users>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // do async operation to fetch users
    }
}

a atividade pode acessar essa lista da seguinte maneira:

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

Minha pergunta é, eu vou fazer isso:

  1. na função loadUsers() eu estou buscando os dados de forma assíncrona onde vou primeiro verificar o banco de dados (Room) para esses dados

  2. Se eu não obtiver os dados lá, farei uma chamada da API para buscar os dados do servidor da web.

  3. Vou inserir os dados buscados no banco de dados (Room) e atualizar a interface do usuário de acordo com os dados.

Qual é a abordagem recomendada para fazer isso?

Se eu iniciar um Service para chamar a API do método loadUsers() , como posso atualizar a MutableLiveData<List<User>> users desse Service ?


Dê uma olhada no developer.android.com/topic/libraries/architecture/guide.html do developer.android.com/topic/libraries/architecture/guide.html que acompanha os novos módulos de arquitetura, como LiveData e ViewModel . Eles discutem essa questão exata em profundidade.

Em seus exemplos, eles não o colocam em serviço. Dê uma olhada em como eles resolvem usando um módulo de repositório e Retrofit. Os adendos na parte inferior incluem exemplos mais completos, incluindo o estado da rede de comunicação, relatórios de erros, etc.


Por favor, use o método postValue (..) de dados ao vivo do thread de segundo plano.

private void loadUsers() {
    // do async operation to fetch users and use postValue() method
   users.postValue(listOfData)
}

Se você está chamando sua API no repositório,

No Repositório :

public MutableLiveData<LoginResponseModel> checkLogin(LoginRequestModel loginRequestModel) {
    final MutableLiveData<LoginResponseModel> data = new MutableLiveData<>();
    apiService.checkLogin(loginRequestModel)
            .enqueue(new Callback<LoginResponseModel>() {
                @Override
                public void onResponse(@NonNull Call<LoginResponseModel> call, @Nullable Response<LoginResponseModel> response) {
                    if (response != null && response.isSuccessful()) {
                        data.postValue(response.body());
                        Log.i("Response ", response.body().getMessage());
                    }
                }

                @Override
                public void onFailure(@NonNull Call<LoginResponseModel> call, Throwable t) {
                    data.postValue(null);
                }
            });
    return data;
}

Em ViewModel

public LiveData<LoginResponseModel> getUser() {
    loginResponseModelMutableLiveData = repository.checkLogin(loginRequestModel);
    return loginResponseModelMutableLiveData;
}

Em atividade / fragmento

loginViewModel.getUser().observe(LoginActivity.this, loginResponseModel -> {
        if (loginResponseModel != null) {
            Toast.makeText(LoginActivity.this, loginResponseModel.getUser().getType(), Toast.LENGTH_SHORT).show();
        }
    });

Nota: Usando JAVA_1.8 lambda aqui, você pode usar sem ele





android-architecture-components