From 102f3e8a04a893eac283de4f2a204edfaad789fe Mon Sep 17 00:00:00 2001 From: Nite Date: Thu, 24 Sep 2020 20:32:51 +0200 Subject: [PATCH] Updated ServerSettingsModel to use Room for handling LiveData --- .../ultrasonic/activity/ServerRowAdapter.kt | 11 +- .../activity/ServerSettingsModel.kt | 123 ++++++++---------- .../moire/ultrasonic/data/ServerSettingDao.kt | 16 ++- 3 files changed, 78 insertions(+), 72 deletions(-) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/ServerRowAdapter.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/ServerRowAdapter.kt index f0baf6ca..3fc21977 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/ServerRowAdapter.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/ServerRowAdapter.kt @@ -53,7 +53,7 @@ internal class ServerRowAdapter( } override fun getCount(): Int { - return if (manageMode) data.size - 1 else data.size + return if (manageMode) data.size else data.size + 1 } override fun getItem(position: Int): Any { @@ -81,8 +81,13 @@ internal class ServerRowAdapter( val image = vi?.findViewById(R.id.server_image) val serverMenu = vi?.findViewById(R.id.server_menu) - text?.text = data.single { setting -> setting.index == index }.name - description?.text = data.single { setting -> setting.index == index }.url + if (index == 0) { + text?.text = context.getString(R.string.main_offline) + description?.text = "" + } else { + text?.text = data.singleOrNull { setting -> setting.index == index }?.name ?: "" + description?.text = data.singleOrNull { setting -> setting.index == index }?.url ?: "" + } // Provide icons for the row if (index == 0) { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/ServerSettingsModel.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/ServerSettingsModel.kt index 95297be8..bf559950 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/ServerSettingsModel.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/activity/ServerSettingsModel.kt @@ -5,12 +5,10 @@ import android.content.SharedPreferences import android.preference.PreferenceManager import android.util.Log import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import org.moire.ultrasonic.R import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.data.ServerSetting import org.moire.ultrasonic.data.ServerSettingDao @@ -23,7 +21,6 @@ class ServerSettingsModel( private val activeServerProvider: ActiveServerProvider, private val context: Context ) : ViewModel() { - private var serverList: MutableLiveData> = MutableLiveData() companion object { private val TAG = ServerSettingsModel::class.simpleName @@ -84,16 +81,13 @@ class ServerSettingsModel( * This function is asynchronous, uses LiveData to provide the Setting. */ fun getServerList(): LiveData> { - viewModelScope.launch { - var dbServerList = repository.loadAllServerSettings().toMutableList() - if (areIndexesMissing(dbServerList)) { - dbServerList = reindexSettings(dbServerList).toMutableList() + // This check should run before returning any result + runBlocking { + if (areIndexesMissing()) { + reindexSettings() } - - dbServerList.add(0, ServerSetting(context.getString(R.string.main_offline), "")) - serverList.value = dbServerList } - return serverList + return repository.loadAllServerSettings() } /** @@ -101,55 +95,47 @@ class ServerSettingsModel( * This function is asynchronous, uses LiveData to provide the Setting. */ fun getServerSetting(index: Int): LiveData { - val result = MutableLiveData() - viewModelScope.launch { - val dbServer = repository.findByIndex(index) - result.value = dbServer - Log.d(TAG, "getServerSetting($index) returning $dbServer") - } - return result + return repository.getLiveServerSettingByIndex(index) } /** * Moves a Setting up in the Server List by decreasing its index */ fun moveItemUp(index: Int) { - if (index == 1) return - - val itemToBeMoved = serverList.value?.single { setting -> setting.index == index } - val previousItem = serverList.value?.single { setting -> setting.index == index - 1 } - - itemToBeMoved?.index = previousItem!!.index - previousItem.index = index + if (index <= 1) return viewModelScope.launch { - repository.update(itemToBeMoved!!, previousItem) - } + val itemToBeMoved = repository.findByIndex(index) + val previousItem = repository.findByIndex(index - 1) - activeServerProvider.invalidateCache() - // Notify the observers of the changed values - serverList.value = serverList.value + if (itemToBeMoved != null && previousItem != null) { + itemToBeMoved.index = previousItem.index + previousItem.index = index + + repository.update(itemToBeMoved, previousItem) + activeServerProvider.invalidateCache() + } + } } /** * Moves a Setting down in the Server List by increasing its index */ fun moveItemDown(index: Int) { - if (index == (serverList.value!!.size - 1)) return - - val itemToBeMoved = serverList.value?.single { setting -> setting.index == index } - val nextItem = serverList.value?.single { setting -> setting.index == index + 1 } - - itemToBeMoved?.index = nextItem!!.index - nextItem.index = index - viewModelScope.launch { - repository.update(itemToBeMoved!!, nextItem) - } + if (index < repository.getMaxIndex() ?: 0) { + val itemToBeMoved = repository.findByIndex(index) + val nextItem = repository.findByIndex(index + 1) - activeServerProvider.invalidateCache() - // Notify the observers of the changed values - serverList.value = serverList.value + if (itemToBeMoved != null && nextItem != null) { + itemToBeMoved.index = nextItem.index + nextItem.index = index + + repository.update(itemToBeMoved, nextItem) + activeServerProvider.invalidateCache() + } + } + } } /** @@ -158,24 +144,15 @@ class ServerSettingsModel( fun deleteItem(index: Int) { if (index == 0) return - val newList = serverList.value!!.toMutableList() - val itemToBeDeleted = newList.single { setting -> setting.index == index } - newList.remove(itemToBeDeleted) - - for (x in index + 1 until newList.size + 1) { - newList.single { setting -> setting.index == x }.index-- - } - viewModelScope.launch { - repository.delete(itemToBeDeleted) - for (x in index until newList.size) { - repository.update(newList.single { setting -> setting.index == x }) + val itemToBeDeleted = repository.findByIndex(index) + if (itemToBeDeleted != null) { + repository.delete(itemToBeDeleted) + Log.d(TAG, "deleteItem deleted index: $index") + reindexSettings() + activeServerProvider.invalidateCache() } } - - activeServerProvider.invalidateCache() - serverList.value = newList - Log.d(TAG, "deleteItem deleted index: $index") } /** @@ -242,9 +219,9 @@ class ServerSettingsModel( * concurrency or migration errors) may get them out of order. * This would make the List Adapter crash, so it is best to prepare and check the list. */ - private fun areIndexesMissing(settings: List): Boolean { - for (i in 1 until settings.size + 1) { - if (!settings.any { s -> s.index == i }) return true + private suspend fun areIndexesMissing(): Boolean { + for (i in 1 until getMaximumIndexToCheck() + 1) { + if (repository.findByIndex(i) == null) return true } return false } @@ -252,13 +229,23 @@ class ServerSettingsModel( /** * This function updates all the Server Settings in the DB so their indexing is continuous. */ - private suspend fun reindexSettings(settings: List): List { - val sortedSettings = settings.sortedBy { t -> t.index } - for (i in sortedSettings.indices) { - sortedSettings[i].index = i + 1 - repository.update(sortedSettings[i]) - Log.d(TAG, "reindexSettings saved ${sortedSettings[i]}") + private suspend fun reindexSettings() { + var newIndex = 1 + for (i in 1 until getMaximumIndexToCheck() + 1) { + var setting = repository.findByIndex(i) + if (setting != null) { + setting.index = newIndex + newIndex++ + repository.update(setting) + Log.d(TAG, "reindexSettings saved $setting") + } } - return sortedSettings + } + + private suspend fun getMaximumIndexToCheck(): Int { + val rowsInDatabase = repository.count() ?: 0 + val indexesInDatabase = repository.getMaxIndex() ?: 0 + if (rowsInDatabase > indexesInDatabase) return rowsInDatabase + return indexesInDatabase } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSettingDao.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSettingDao.kt index 27c289b3..c715892e 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSettingDao.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/data/ServerSettingDao.kt @@ -1,5 +1,6 @@ package org.moire.ultrasonic.data +import androidx.lifecycle.LiveData import androidx.room.Dao import androidx.room.Delete import androidx.room.Insert @@ -35,7 +36,7 @@ interface ServerSettingDao { * Loads all Server Settings from the table */ @Query("SELECT * FROM serverSetting") - suspend fun loadAllServerSettings(): Array + fun loadAllServerSettings(): LiveData> /** * Finds a Server Setting by its unique Id @@ -49,6 +50,13 @@ interface ServerSettingDao { @Query("SELECT * FROM serverSetting WHERE [index] = :index") suspend fun findByIndex(index: Int): ServerSetting? + /** + * Finds a Server Setting by its Index in the Select List + * @return LiveData of the ServerSetting + */ + @Query("SELECT * FROM serverSetting WHERE [index] = :index") + fun getLiveServerSettingByIndex(index: Int): LiveData + /** * Retrieves the count of rows in the table */ @@ -60,4 +68,10 @@ interface ServerSettingDao { */ @Query("SELECT MAX([id]) FROM serverSetting") suspend fun getMaxId(): Int? + + /** + * Retrieves the greatest value of the Index column in the table + */ + @Query("SELECT MAX([index]) FROM serverSetting") + suspend fun getMaxIndex(): Int? }