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:
-
en la función
loadUsers()
estoy obteniendo los datos de forma asincrónica, donde primero comprobaré la base de datos (Room) para esos datos -
Si no obtengo los datos allí, haré una llamada a la API para obtener los datos del servidor web.
-
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.
developer.android.com/topic/libraries/architecture/guide.html
Tiene muy buenas respuestas para tu problema. Desplácese hasta el final para ver cómo puede guardar la respuesta en su base de datos y actualizar la interfaz de usuario utilizando LiveData.