其数据由异步任务加载的 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 是唯一一个被自己使用是没有意义的。其他两个可以带来一些优势,但是当您使用所有这些时,就会发挥全部作用。 您还将度过愉快的时光,为您的实施编写测试。