Updated ServerSettingsModel to use Room for handling LiveData

This commit is contained in:
Nite 2020-09-24 20:32:51 +02:00
parent 5b0c9906f1
commit 102f3e8a04
No known key found for this signature in database
GPG Key ID: 1D1AD59B1C6386C1
3 changed files with 78 additions and 72 deletions

View File

@ -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<ImageView>(R.id.server_image)
val serverMenu = vi?.findViewById<ImageButton>(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) {

View File

@ -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<List<ServerSetting>> = 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<List<ServerSetting>> {
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<ServerSetting?> {
val result = MutableLiveData<ServerSetting?>()
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<ServerSetting>): 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<ServerSetting>): List<ServerSetting> {
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
}
}

View File

@ -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<ServerSetting>
fun loadAllServerSettings(): LiveData<List<ServerSetting>>
/**
* 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<ServerSetting?>
/**
* 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?
}