【问题标题】:AsyncTask, AsynTaskLoader or Executer with ViewModel, LiveData and Room?AsyncTask、AsyncTaskLoader 还是带有 ViewModel、LiveData 和 Room 的 Executor?
【发布时间】:2019-03-12 05:23:56
【问题描述】:

首先,我不了解 Android 和 Java 的所有内容,我正在研究这方面的内容,以防您发现我的问题缺乏相关知识。

当我读到 Loaders 的好处时,我读到加载器在单独的线程上运行以防止 UI 无响应。

出现并阅读ViewModel和LiveData和房间后以及阅读this post后,尤其是在部分 观察数据说

在Loader 的世界中,将数据传输到 UI 将涉及 LoaderManager,在正确的地方调用initLoader(),并构建一个> ?LoaderCallbacks。世界变得更简单 架构组件世界。等等。

下一节

加载第二段中所说的所有内容

例如,Room 允许您进行可观察的查询 — 数据库查询 返回LiveData 以便数据库更改自动向上传播 通过您的ViewModel 到您的用户界面。有点像CursorLoader 没有 触摸光标或加载器。

以上所有都意味着 ViewModel 和 LiveData 与 Room 可以在后台线程中工作,我意思是当我们使用 ViewModel 和 LiveData 和 Room 而不是 Loaders 时,我们不需要使用 AsyncTask 或 AsyncTaskLoader 或 Executer

但在这些例子中:

android-room-with-a-view,正如他们在 README.md 中所说,可以用作模板,

在MainActivity.java中他们写了mWordViewModel.getAllWords().observe(this, .... ;,如果我们深入追踪getAllWords()我们会发现该函数是select的查询,但是当他们想要在 WordRepository.java 中插入数据 或 WordRoomDatabase.java 他们使用 AsyncTask,

我的意思是为什么他们使用 ViewModel 和 LiveData 和 Dao 来查询 select,并且在insert 的查询,他们 included AsyncTask 与 ViewModel 和 Dao?,因为作为上面的 ViewModel 和带有 Room 的 LiveData 意味着什么可以在后台线程中工作?

我之前的问题是针对此示例 android-persistence at step3_solution,我的意思是 获取 仅使用 ViewModel 的数据,但要插入 数据,例如在DatabaseInitializer.java 中,AsyncTask 是否被包含?

同样在BasicSample 的这个示例中,当必须插入数据时,Executer 是否包含?

非常感谢

【问题讨论】:

  • 在协程中使用 Kotlin

标签: java android android-room android-livedata android-viewmodel


【解决方案1】:

他们在MainActivity.java中写了mWordViewModel.getAllWords().observe(this, .... ;如果我们深入追踪getAllWords()我们会发现这个函数是select的查询,

确实,getAllWords() 从 Room DAO 暴露为 LiveData<List<T>>,因此可以观察到,Room 内部将处理异步获取任务(在 ArchTaskExecutor.io() 上执行,这是一个 two-threaded executor)。

@Query("SELECT * from word_table ORDER BY word ASC")
LiveData<List<Word>> getAlphabetizedWords();

但是,如果您有 insert,那么 Room DAO 是同步方法,因此它们不会为您处理线程。


AsyncTask 是让您的代码在 Android 的默认执行程序(阅读:后台线程)上执行后台任务的一种特殊方式:

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

按顺序运行每个任务。



所以你的问题的答案是,因为查询和插入的工作方式不同。

显示为 LiveData 的查询正在跟踪基础数据库的失效,并在您执行会更改此表的写入时为您重新查询结果集。这样,当您执行更改特定表中的元素的写入时,您无需手动查询数据库。其实很方便。

插入只是插入。所以在这种情况下,他们不会为你施展魔法。

【讨论】:

  • AsyncTask 是一个可行的解决方案吗?
  • 为什么你的回答中提到了AsyncTask?
  • @IgorGanapolsky 因为 AsyncTask 在写完这个答案大约 6 个月后被弃用了,可能
【解决方案2】:

以上所有都意味着 ViewModel 和 LiveData with Room 可以在后台线程中工作,我的意思是当我们使用 ViewModel 和 LiveData with Room 而不是 Loaders 时,我们不需要使用 AsyncTask 或 AsyncTaskLoader 或 Executer

他们没有。它们在它们被执行的当前线程上运行。这就是为什么在您引用的示例中他们仍然使用 AsyncTask 将工作移动到后台线程的原因。

还要注意 MutableLiveData 有两种方法来设置它的值。

public void postValue(T value) {
    super.postValue(value);
}

public void setValue(T value) {
    super.setValue(value);
}

postValue(value) 用于在后台线程中设置MutableLiveData 的值。如果我没记错的话,在后台调用setValue(value) 会抛出异常。

此外,从 API 28 开始不推荐使用加载程序。您可以阅读它here。

从 Android P (API 28) 开始,加载程序已被弃用。在处理 Activity 和 Fragment 生命周期时处理加载数据的推荐选项是使用 ViewModel 和 LiveData 的组合。 ViewModel 可以像 Loaders 一样在配置更改中幸存下来,但样板文件更少。 LiveData 提供了一种生命周期感知方式来加载您可以在多个 ViewModel 中重用的数据。您还可以使用 MediatorLiveData 组合 LiveData,任何可观察的查询,例如来自 Room 数据库的查询,都可用于观察数据的变化。 ViewModels 和 LiveData 在您无权访问 LoaderManager 的情况下也可用,例如在服务中。将两者结合使用提供了一种简单的方法来访问您的应用程序所需的数据,而无需处理 UI 生命周期。要了解有关 LiveData 的更多信息,请参阅 LiveData 指南;要了解有关 ViewModel 的更多信息,请参阅 ViewModel 指南。

【讨论】:

  • 我们应该使用 AsyncTask 吗?
  • 如果你想在主线程之外工作以避免阻塞主线程,除了AsyncTask之外,还有更多的选项可供你使用。换句话说,不惜一切代价避免AsyncTask。
猜你喜欢
  • 2019-07-17
  • 1970-01-01
  • 2021-01-04
  • 2019-02-04
  • 1970-01-01
  • 1970-01-01
  • 2019-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多