I am using Room as database for my Android TV app. I have four different entities: account, category, channel, data. In my MainFragment I am showing 3 recyclerviews, side-by-side.
The first shows the activated accounts (where account.isActive = 1), the second, shows the categories (category.favorite = 1) of the related account, when the accounts gets the focus. And then there is the channelwithdata-recyclerview, that shows the related channels of a category (where channel.isSelected = 1) with its related information (data) when a category gets the focus.
So there can be multiple accounts, where every account can have multiple categories, and each of the categories has multiple channels with it's data.
At the moment on app start in the onCreate of the MainActivity I am calling 3 viewmodel functions that get the related data from the database as LiveData and save each in a variable in the viewmodel. For example I am calling:
viewmodel.getActivatedAccounts() in the MainActivity
-> in the viewmodel I have:
accountsLiveData: LiveData<List<Account>>? = null
and
private fun getActivatedAccounts() =
viewModelScope.launch {
accountsLiveData = dao.getActivatedAccounts()
}
and the dao-function is:
fun getActivatedAccounts(): LiveData<List<Account>>
It's working fine for account and category, but when I get to channelsWithData (so the relation between Channel and Data ->
data class ChannelsWithData(
@Embedded var channel: Channel,
@Relation(
entity = Data::class,
parentColumn = "dataChannelId",
entityColumn = "dataChannelId"
)
var dataList: List<Data>
))
with the dao-function:
@Transaction
@Query("SELECT * FROM channel WHERE isSelected = 1")
fun getAllSelectedChannelsWithData(): LiveData<List<ChannelsWithData>>
I noticed that when I install an update of the app on the first start of the update it loads fast (about 1-2 seconds), but when I start the app again it takes about 15-20 seconds.
So what I wanted to ask is: Is it a good idea to fetch all the data I will need, on app-start, and if yes, is it a good approach to save it in a viewmodel livedata-variable like I am doing it at the moment. Or is it better to call a new query like:
@Query("SELECT * FROM Channel WHERE accountId = :accountId AND category_id = :categoryId")
fun getChannelsWithDataPerCategoryAndAccount(accountId: Long, categoryId: String): LiveData<List<ChannelsWithData>>
everytime a category get's the focus?
My goal is to minimize the waiting time as much as possbile for the user when he is navigating throw the accounts, categories and channels. Preferably there shouldn't be any. On the other hand, I don't want that the user has to wait nearly 20 seconds before he can start navigating :-)
I don't know how heavy is your query, and how much data you are processing but I think there is couple of things that you can include in order to not experience long delay. First if you have too much data add pagination for your recycler views. Second, I don't think in your case saving the data in viewModel would be a good idea. I think you are doing everything on your Main thread and instead, you can use coroutine and do fetching on background thread to minimize the waiting time. On the other hand you can use caching and fetch data on demand, and if it has changed, not every time! Plus the query you have used seems not efficient in your case. Your last list is depending on two rows in your table which creates a delay. You can divide this query into two parallel query at the same time on two different thread. And why using livedata? is there a need? you can use sharedflow instead.
Or even not using LiveData in your dao and emit flow there.