其数据由异步任务加载的 ViewModel
ViewModel whose data is loaded by an async task
当你有异步加载的数据时,我只是对 ViewModel 的想法感到困惑。
这是一个 ViewModel 的例子
public class UsersViewModel extends ViewModel {
private List<User> userList;
public List<User> getUserList() {
if (userList == null) {
usersList = loadUsers();
}
return userList;
}
private List<User> loadUsers() {
// This is async task
}
}
Activity:
public class UsersActivity extends AppCompatActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
UsersViewModel usersViewModel =
ViewModelProviders.of(this).get(UsersViewModel.class);
showUsers(usersViewModel.getUserList());
}
}
这将显示一个空列表(或者可能在 null 时崩溃),因为异步任务尚未完成。我在网上看到的所有示例都是同步阻塞调用。但是如果是异步调用,它会从服务器获取数据并更新 UI 作为结果。我们如何处理?
您可以使用实时数据实现这一目标。 ViewModel 将 return MutableLiveData 并且在您的视图中,您将订阅任何值更改。
您也可以使用数据绑定,然后您的视图数据会自动更改。
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<String>();
}
return mCurrentName;
}
// Rest of the ViewModel...
}
然后在你的 Activity:
public class NameActivity extends AppCompatActivity {
private NameViewModel mModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code to setup the activity...
// Get the ViewModel.
mModel = ViewModelProviders.of(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
mNameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
mModel.getCurrentName().observe(this, nameObserver);
}
}
https://developer.android.com/topic/libraries/architecture/livedata
正如 Felipe R. 在他的回答中所建议的那样,您可以使用 LiveData 实现它,但我会说您不应该就此止步。
当您将所有架构组件组合使用时,Android 架构组件的真正威力就会发挥出来。
- ViewModel——当您想从后台线程或其他长 运行 进程更新 UI 时,这将使您的生活更轻松,因为它们链接到 Activit/Fragment生命周期,但以独立的方式,因此当您的 AsyncTask 发布作业结果时,从 window 中删除的视图不再有 NPE。
- LiveData -- 将帮助您将数据从 ViewModel 传输到 UI,而不用担心哪个线程返回了响应。对于 Kotlin,LiveData 可以替换为 RxJava 或 Rx,但我更喜欢它 UI 更新
- 数据绑定 -- 将在信息存在时帮助您 "auto-update" UI,还会时不时地让您免于一些 NPE。
在这 3 个组件中,我认为 ViewModel 是唯一一个被自己使用是没有意义的。其他两个可以带来一些优势,但是当您使用所有这些时,就会发挥全部作用。
您还将度过愉快的时光,为您的实施编写测试。
当你有异步加载的数据时,我只是对 ViewModel 的想法感到困惑。
这是一个 ViewModel 的例子
public class UsersViewModel extends ViewModel {
private List<User> userList;
public List<User> getUserList() {
if (userList == null) {
usersList = loadUsers();
}
return userList;
}
private List<User> loadUsers() {
// This is async task
}
}
Activity:
public class UsersActivity extends AppCompatActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
UsersViewModel usersViewModel =
ViewModelProviders.of(this).get(UsersViewModel.class);
showUsers(usersViewModel.getUserList());
}
}
这将显示一个空列表(或者可能在 null 时崩溃),因为异步任务尚未完成。我在网上看到的所有示例都是同步阻塞调用。但是如果是异步调用,它会从服务器获取数据并更新 UI 作为结果。我们如何处理?
您可以使用实时数据实现这一目标。 ViewModel 将 return MutableLiveData 并且在您的视图中,您将订阅任何值更改。
您也可以使用数据绑定,然后您的视图数据会自动更改。
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<String>();
}
return mCurrentName;
}
// Rest of the ViewModel...
}
然后在你的 Activity:
public class NameActivity extends AppCompatActivity {
private NameViewModel mModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code to setup the activity...
// Get the ViewModel.
mModel = ViewModelProviders.of(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
mNameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
mModel.getCurrentName().observe(this, nameObserver);
}
}
https://developer.android.com/topic/libraries/architecture/livedata
正如 Felipe R. 在他的回答中所建议的那样,您可以使用 LiveData 实现它,但我会说您不应该就此止步。
当您将所有架构组件组合使用时,Android 架构组件的真正威力就会发挥出来。
- ViewModel——当您想从后台线程或其他长 运行 进程更新 UI 时,这将使您的生活更轻松,因为它们链接到 Activit/Fragment生命周期,但以独立的方式,因此当您的 AsyncTask 发布作业结果时,从 window 中删除的视图不再有 NPE。
- LiveData -- 将帮助您将数据从 ViewModel 传输到 UI,而不用担心哪个线程返回了响应。对于 Kotlin,LiveData 可以替换为 RxJava 或 Rx,但我更喜欢它 UI 更新
- 数据绑定 -- 将在信息存在时帮助您 "auto-update" UI,还会时不时地让您免于一些 NPE。
在这 3 个组件中,我认为 ViewModel 是唯一一个被自己使用是没有意义的。其他两个可以带来一些优势,但是当您使用所有这些时,就会发挥全部作用。 您还将度过愉快的时光,为您的实施编写测试。