0

First I don't know everything in Android and Java I am working on that, in case you find lack of knowledge in my question.

When I read about the benefits of Loaders, I read that loaders run on separate threads to prevent unresponsive UI.

After appearing and reading of ViewModel and LiveData and Room and after reading this post, especially in the section Observing data which says

In the Loader world, getting your data to your UI would involve a LoaderManager, calling initLoader() in the right place, and building a > ?LoaderCallbacks. The world is a bit more straightforward in the Architecture Components world. etc..

and the next section

Load all the things which says in the second paragraph

For example, Room lets you have observarable queries — database queries that return LiveData so that database changes automatically propagate up through your ViewModel to your UI. Kind of like a CursorLoader without touching Cursors or Loaders.

All of the above implies that ViewModel and LiveData with Room can work in the background thread, I mean when we use ViewModel and LiveData with Room instead of Loaders, we needn't have used AsyncTask or AsyncTaskLoader or Executer

But in theses examples:

android-room-with-a-view which can be used as a template as they say in README.md,

In the MainActivity.java they write mWordViewModel.getAllWords().observe(this, .... ; and if we trace getAllWords() deeply we find that the function is query of select, but when they want to insert data in WordRepository.java or WordRoomDatabase.java they use AsyncTask,

I mean why have they used ViewModel and LiveData and Dao with query of select, and in the query of insert they have included AsyncTask with ViewModel and Dao?, because as what implies above ViewModel and LiveData with Room can work in the background thread?

My previous question goes for this example android-persistence at step3_solution, I mean to get the data only ViewModel is used but to insert data like in DatabaseInitializer.java, AsyncTask is included?

Also in this example of BasicSample, Executer is included when data has to be inserted?

Thank you very much

mbmc
  • 5,024
  • 5
  • 25
  • 53
moamarubuntu
  • 55
  • 1
  • 9

2 Answers2

0

In the MainActivity.java they write mWordViewModel.getAllWords().observe(this, .... ; and if we trace getAllWords() deeply we find that the function is query of select,

Indeed, the getAllWords() is exposed from Room DAO as LiveData<List<T>>, therefore it can be observed, and internally Room will handle the asynchronous fetch task (executed on ArchTaskExecutor.io() which is a two-threaded executor).

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

However, if you have an insert, then on Room DAO that is synchronous method, so they don't handle threading for you.


AsyncTask is one particular way to have your code executed on Android's default executor (read: a background thread) for background tasks:

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

Which runs every task sequentially.



So the answer to your question is that because queries and inserts work differently.

Queries exposed as LiveData are tracking invalidation of the underlying database and re-query the result set for you if you did a write that would have changed this table. This way you don't need to manually query the database when you do a write that changes elements in a particular table. It is very convenient, actually.

Inserts are just, inserts. So they don't do magic for you in that case.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
-1

All of the above implies that ViewModel and LiveData with Room can work in the background thread, I mean when we use ViewModel and LiveData with Room instead of Loaders, we needn't have used AsyncTask or AsyncTaskLoader or Executer

They don't. They run on the current thread they were executed. That is exactly why in the example you cited they still used an AsyncTask to move the work to a background thread.

Notice also that MutableLiveData have two methods to set its values.

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

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

postValue(value) is used to set the value of a MutableLiveData when in a background thread. Calling the setValue(value) while in the background will throw an exception if I remember it right.

Also, Loaders are deprecated as of API 28. You can read it here.

Loaders have been deprecated as of Android P (API 28). The recommended option for dealing with loading data while handling the Activity and Fragment lifecycles is to use a combination of ViewModels and LiveData. ViewModels survive configuration changes like Loaders but with less boilerplate. LiveData provides a lifecycle-aware way of loading data that you can reuse in multiple ViewModels. You can also combine LiveData using MediatorLiveData , and any observable queries, such as those from a Room database, can be used to observe changes to the data. ViewModels and LiveData are also available in situations where you do not have access to the LoaderManager, such as in a Service. Using the two in tandem provides an easy way to access the data your app needs without having to deal with the UI lifecycle. To learn more about LiveData see the LiveData guide and to learn more about ViewModels see the ViewModel guide.

Archie G. Quiñones
  • 11,638
  • 18
  • 65
  • 107