livedata jetpack example ejemplo developer android viewmodel background-service android-room android-architecture-components

jetpack - viewmodel android architecture



Cómo actualizar LiveData de un ViewModel desde el servicio en segundo plano y actualizar la interfaz de usuario (6)

... en la función loadUsers () estoy recuperando los datos de forma asíncrona ... Si inicio un servicio para llamar a la API desde el método loadUsers (), ¿cómo puedo actualizar la variable de usuarios MutableLiveData> de ese servicio?

Si la aplicación está obteniendo datos de usuario en un hilo de fondo, postValue (en lugar de setValue ) será útil.

En el método loadData hay una referencia al objeto "usuarios" MutableLiveData. El método loadData también obtiene algunos datos de usuario nuevos de algún lugar (por ejemplo, un repositorio).

Ahora, si la ejecución está en un hilo de fondo, MutableLiveData.postValue () actualiza los observadores externos del objeto MutableLiveData.

Tal vez algo como esto:

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

Recientemente estoy explorando la arquitectura de Android, que ha sido introducida recientemente por Google. De la Documentation he encontrado esto:

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

la actividad puede acceder a esta lista de la siguiente manera:

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

Mi pregunta es, voy a hacer esto:

  1. en la función loadUsers() estoy obteniendo los datos de forma asincrónica, donde primero comprobaré la base de datos (Room) para esos datos

  2. Si no obtengo los datos allí, haré una llamada a la API para obtener los datos del servidor web.

  3. Insertaré los datos recuperados en la base de datos (Room) y actualizaré la IU de acuerdo con los datos.

¿Cuál es el enfoque recomendado para hacer esto?

Si inicio un Service para llamar a la API desde el método loadUsers() , ¿cómo puedo actualizar la variable de MutableLiveData<List<User>> users de ese Service ?


Eche un vistazo a la developer.android.com/topic/libraries/architecture/guide.html que acompaña a los nuevos módulos de arquitectura como LiveData y ViewModel . Discuten este tema exacto en profundidad.

En sus ejemplos no lo ponen en un servicio. Eche un vistazo a cómo lo resuelven utilizando un módulo de "repositorio" y Retrofit. Los apéndices en la parte inferior incluyen ejemplos más completos que incluyen el estado de la red de comunicación, informes de errores, etc.


Por favor, use el método postValue (..) de datos en vivo del hilo de fondo.

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


Si está llamando a su API en el repositorio, entonces,

En repositorio :

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

En ViewModel

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

En actividad / 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 aquí, puede usar sin él


Supongo que está utilizando componentes de arquitectura de Android . En realidad, no importa donde llame al service, asynctask or handler para actualizar los datos. Puede insertar los datos del servicio o del asinctask utilizando el método postValue(..) . Tu clase se vería así:

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

Como los users son LiveData , la base de datos de Room es responsable de proporcionar los datos de los usuarios donde sea que se inserten.

Note: En una arquitectura similar a MVVM, el repositorio es el principal responsable de verificar y extraer datos locales y datos remotos.