如何从后台服务更新 ViewModel 的 LiveData 和 Update UI
How to update LiveData of a ViewModel from background service and Update UI
最近我正在探索 Android 架构,该架构最近由 google 介绍。从 Documentation 我发现了这个:
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
}
}
activity 可以按如下方式访问此列表:
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
});
}
}
我的问题是,我要这样做:
在 loadUsers()
函数中我正在异步获取数据,我将首先检查数据库(房间)中的数据
如果我没有在那里获取数据,我将进行 API 调用以从 Web 服务器获取数据。
我会将获取的数据插入数据库(房间)并根据数据更新UI。
执行此操作的推荐方法是什么?
如果我启动一个 Service
以从 loadUsers()
方法调用 API,我如何从 Service
更新 MutableLiveData<List<User>> users
变量?
我假设您正在使用 android architecture components。实际上,无论您在哪里调用 service, asynctask or handler
来更新数据都没有关系。您可以使用 postValue(..)
方法从服务或异步任务插入数据。您的 class 将如下所示:
private void loadUsers() {
// do async operation to fetch users and use postValue() method
users.postValue(listOfData)
}
由于 users
是 LiveData
,Room
数据库负责在插入的任何位置提供用户数据。
Note:
在类似MVVM的架构中,repository主要负责检查和拉取本地数据和远程数据。
看看 Android architecture guide 伴随新架构模块的 LiveData
和 ViewModel
。他们深入讨论了这个确切的问题。
在他们的示例中,他们没有将其放入服务中。看看他们是如何使用 "repository" 模块和 Retrofit 解决这个问题的。底部的附录包括更完整的示例,包括通信网络状态、报告错误等。
... in the loadUsers() function I am fetching the data asynchronously ...
If I start a Service to call the API from the loadUsers() method, how
can I update the MutableLiveData> users variable from that
Service?
如果应用在后台线程上获取用户数据,postValue (rather than setValue) 将很有用。
在 loadData 方法中有一个对 MutableLiveData "users" 对象的引用。 loadData 方法还从某处(例如,存储库)获取一些新的用户数据。
现在,如果在后台线程上执行,MutableLiveData.postValue() 会更新 MutableLiveData 对象的外部观察者。
也许是这样的:
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);
}
});
}
您可以从后台线程使用 MutableLiveData<T>.postValue(T value)
方法。
private void loadUsers() {
// do async operation to fetch users and use postValue() method
users.postValue(listOfData)
}
如果您在存储库中调用 api,那么
在存储库中:
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;
}
在ViewModel
public LiveData<LoginResponseModel> getUser() {
loginResponseModelMutableLiveData = repository.checkLogin(loginRequestModel);
return loginResponseModelMutableLiveData;
}
在Activity/Fragment
loginViewModel.getUser().observe(LoginActivity.this, loginResponseModel -> {
if (loginResponseModel != null) {
Toast.makeText(LoginActivity.this, loginResponseModel.getUser().getType(), Toast.LENGTH_SHORT).show();
}
});
注意:这里使用JAVA_1.8 lambda,不用它也可以使用
最近我正在探索 Android 架构,该架构最近由 google 介绍。从 Documentation 我发现了这个:
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
}
}
activity 可以按如下方式访问此列表:
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
});
}
}
我的问题是,我要这样做:
在
loadUsers()
函数中我正在异步获取数据,我将首先检查数据库(房间)中的数据如果我没有在那里获取数据,我将进行 API 调用以从 Web 服务器获取数据。
我会将获取的数据插入数据库(房间)并根据数据更新UI。
执行此操作的推荐方法是什么?
如果我启动一个 Service
以从 loadUsers()
方法调用 API,我如何从 Service
更新 MutableLiveData<List<User>> users
变量?
我假设您正在使用 android architecture components。实际上,无论您在哪里调用 service, asynctask or handler
来更新数据都没有关系。您可以使用 postValue(..)
方法从服务或异步任务插入数据。您的 class 将如下所示:
private void loadUsers() {
// do async operation to fetch users and use postValue() method
users.postValue(listOfData)
}
由于 users
是 LiveData
,Room
数据库负责在插入的任何位置提供用户数据。
Note:
在类似MVVM的架构中,repository主要负责检查和拉取本地数据和远程数据。
看看 Android architecture guide 伴随新架构模块的 LiveData
和 ViewModel
。他们深入讨论了这个确切的问题。
在他们的示例中,他们没有将其放入服务中。看看他们是如何使用 "repository" 模块和 Retrofit 解决这个问题的。底部的附录包括更完整的示例,包括通信网络状态、报告错误等。
... in the loadUsers() function I am fetching the data asynchronously ... If I start a Service to call the API from the loadUsers() method, how can I update the MutableLiveData> users variable from that Service?
如果应用在后台线程上获取用户数据,postValue (rather than setValue) 将很有用。
在 loadData 方法中有一个对 MutableLiveData "users" 对象的引用。 loadData 方法还从某处(例如,存储库)获取一些新的用户数据。
现在,如果在后台线程上执行,MutableLiveData.postValue() 会更新 MutableLiveData 对象的外部观察者。
也许是这样的:
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);
}
});
}
您可以从后台线程使用 MutableLiveData<T>.postValue(T value)
方法。
private void loadUsers() {
// do async operation to fetch users and use postValue() method
users.postValue(listOfData)
}
如果您在存储库中调用 api,那么
在存储库中:
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;
}
在ViewModel
public LiveData<LoginResponseModel> getUser() {
loginResponseModelMutableLiveData = repository.checkLogin(loginRequestModel);
return loginResponseModelMutableLiveData;
}
在Activity/Fragment
loginViewModel.getUser().observe(LoginActivity.this, loginResponseModel -> {
if (loginResponseModel != null) {
Toast.makeText(LoginActivity.this, loginResponseModel.getUser().getType(), Toast.LENGTH_SHORT).show();
}
});
注意:这里使用JAVA_1.8 lambda,不用它也可以使用