Я переписываю приложение, которое включает получение данных с сервера через REST, сохранение их в базе данных на каждом устройстве Android, а затем отображение этих данных пользователю. Данные, извлекаемые с сервера, имеют параметр «с», поэтому он не будет возвращать все данные, только данные, которые изменились с момента последнего извлечения.
У меня извлечение данных с сервера работает нормально, ноЯ не уверен, что лучший способ сохранить эти данные в базе данных, , а затем показать их пользователю. Я использую Kotlin, Retrofit, Room и LiveData.
Приведенный ниже код является упрощенной версией того, что я на самом деле делаю, но в нем все понятно.
MyData.kt (модель)
@Entity(tableName = "MyTable")
data class MyData(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
var id Int? = null,
@SerializedName("message")
@ColumnInfo(name = "message")
var message: String? = null
) {
companion object {
fun fromContentValues(values: ContentValues): MyData {
val data = MyData()
// Do this for id and message
if (values.containsKey("id") {
data.id = values.getAsInteger("id")
}
}
}
}
DataViewModel.kt
class DataViewModel(application: Application) : AndroidViewModel(application) {
private val repository = DataRepository()
fun data(since: Long) =
liveData(Dispatchers.IO) {
val data = repository.getDataFromServer(since)
emit(data)
}
fun saveData(data: List<MyData>) =
liveData(Dispatchers.Default) {
val result = repository.saveDataToDatabase(data)
emit(result)
}
fun data() =
liveData(Dispatchers.IO) {
val data = repository.getDataFromDatabase()
emit(data)
}
}
DataRepository.kt
class DataRepository(application: Application) {
// I won't add how the Retrofit client is created, it's standard
private var client = "MyUrlToGetDataFrom"
private var myDao: MyDao
init {
val myDatabase = MyDatabase.getDatabase(application)
myDao = myDatabase!!.myDao()
}
suspend fun getDataFromServer(since: Long): List<MyData> {
try {
return client.getData(since)
} catch (e: Exception) {
}
}
fun getDataFromDatabase(): List<MyData> = myDao.getAll()
suspend fun insertData(data: List<MyData>) =
myDao.insertData(data)
}
MyDao.kt
@Dao
interface PostsDao {
@Query("SELECT * FROM " + Post.TABLE_NAME + " ORDER BY " + Post.COLUMN_ID + " desc")
suspend fun getAllData(): List<MyData>
@Insert
suspend fun insertData(data: List<MyData>)
}
ListActivity.kt
private lateinit var mDataViewModel: DataViewModel
override fun onCreate(savedInstanceBundle: Bundle?) {
super.onCreate(savedInstanceBundle)
mDataViewModel = ViewModelProvider(this, DataViewModelFactory(contentResolver)).get(DataViewModel::class.java)
getData()
}
private fun getData() {
mDataViewModel.data(getSince()).observe(this, Observer {
saveData(it)
})
}
private fun saveData(data: List<MyData>) {
mDataViewModel.saveData(data)
mDataViewModel.data().observe(this, Observer {
setupRecyclerView(it)
})
}
ListActivity.kt и, возможно, классы ViewModel и Repository, где он использует сопрограммы, находятся там, где я застрял. getData () извлекает данные с сервера без проблем, но когда дело доходит до сохранения их в базе данных, затем извлечения этих сохраненных данных из базы данных и их отображения пользователю, я не уверен в подходе. Как я уже говорил, я использую Room, но Room не позволит вам получить доступ к базе данных в главном потоке.
Помните, сначала нужно сохранить в базе данных, а затем извлечь из базы данных, поэтому я неЯ не хочу звонить mDataViewModel.data().observe
до тех пор, пока он не сохранится в базе данных.
Каков правильный подход к этому? Я попытался сделать CoroutineScope для mDataViewModel.saveData (), затем .invokeOnCompletion
, чтобы сделать mDataViewModel.data().observe
, но он не сохраняется в базе данных. Я предполагаю, что я делаю мои сопрограммы неправильно, но не уверен, где именно.
Это также в конечном счете необходимо будет удалить и обновить записи из базы данных.