android - 使用kotlin协程中的房间从服务器获取数据后如何将数据保存到数据库?
问题描述
我正在开发新闻应用程序我想在使用房间从服务器获取数据后将数据保存到数据库但我很困惑我已经按照教程但是他们的逻辑不同如何正确保存数据以便在从服务器获取数据后我可以保存数据到数据库?
在我的 SportNewsDatabase.kt 下面
@Database(entities = [Article::class], version = 1, exportSchema = false)
abstract class SportNewsDatabase : RoomDatabase() {
abstract fun sportNewsDao(): SportNewsDao
companion object {
private var instance: SportNewsDatabase? = null
fun getInstance( context: Context): SportNewsDatabase? {
if (instance == null) {
synchronized(SportNewsDatabase::class.java) {
instance = Room.databaseBuilder(context.applicationContext, SportNewsDatabase::class.java, "article_database")
.fallbackToDestructiveMigration()
.build()
}
}
return instance
}
}
}
以下 SportNewsDao.kt
@Dao 界面 SportNewsDao {
@Query("SELECT * FROM article")
fun getAllData(): LiveData<List<Article>>
@Insert
suspend fun addAll(article: List<Article>)
@Update
suspend fun updateArticle(article: Article)
@Delete
suspend fun deleteArticle(article: Article)
}
below my repository class
interface NewsRepository {
// Suspend is used to await the result from Deferred
suspend fun getNewsList(): UseCaseResult<List<Article>>
var sportNewsDao: SportNewsDao
}
fun insertArticle(article: List<Article>){
val insertArticles
}
@Suppress("UNCHECKED_CAST")
class NewsRepositoryImpl(private val sportsNewsApi: SportNewsInterface) : NewsRepository {
override suspend fun getNewsList(): UseCaseResult<List<Article>> {
return try {
val result = sportsNewsApi.getNewsAsync().body()!!.articles
UseCaseResult.Success(result)
} catch (ex: Exception) {
UseCaseResult.Error(ex)
}
}
}
在我使用 Kotlin 协程的 MainViewModel.kt 下面
@Suppress("UNCHECKED_CAST")
class MainViewModel(val newsRepository: NewsRepository) : ViewModel(), CoroutineScope {
// Coroutine's background job
val job = Job()
// Define default thread for Coroutine as Main and add job
override val coroutineContext: CoroutineContext = Dispatchers.Main + job
val showLoading = MutableLiveData<Boolean>()
val sportList = MutableLiveData<List<Article>>()
val showError = SingleLiveEvent<String>()
fun loadNews() {
// Show progressBar during the operation on the MAIN (default) thread
showLoading.value = true
// launch the Coroutine
launch {
// Switching from MAIN to IO thread for API operation
// Update our data list with the new one from API
val result = withContext(Dispatchers.IO) {
newsRepository?.getNewsList()
}
// Hide progressBar once the operation is done on the MAIN (default) thread
showLoading.value = false
when (result) {
is UseCaseResult.Success<*> -> {
sportList.value = result.data as List<Article>
}
is Error -> showError.value = result.message
}
}
}
override fun onCleared() {
super.onCleared()
// Clear our job when the linked activity is destroyed to avoid memory leaks
job.cancel()
}
}
解决方案
@sashabeliy
嗨,我想我有你的问题的解决方案,但我不是 mvvm 和协程方面的专家,所以如果有人有更好的解决方案,我会接受 :)
对于我的应用程序,我在主线程中启动下载,并且只有当我得到响应时,我才使用 Dispatchers.IO 在 Room 中插入接收到的数据。
在视图模型中
fun downLoadPDV(last_update : String) : LiveData<List<PDV>> {
return repositoryPDV.downloadPDV(last_update)
}
在存储库中
fun downloadPDV(last_update : String ): LiveData<List<PDV>> {
val mutableLiveData: MutableLiveData<List<PDV>> = MutableLiveData()
val apiService: ApiInterface = RetrofitClient.getRetrofitClient().create(ApiInterface::class.java)
apiService.CallListPDV(last_update)?.enqueue(object :
Callback<List<PDV>> {
override fun onResponse(
call: Call<List<PDV>>,
response: Response<List<PDV>>
) {
Log.e(ContentValues.TAG, "Download PDV Success => $response")
if (response.isSuccessful && response.body() != null) {
mutableLiveData.setValue(response.body());
GlobalScope.launch(Dispatchers.IO) {
for (pdv in response.body()!!) {
insertPDV(pdv)
}
}
}
}
override fun onFailure(call: Call<List<PDV>>, t: Throwable) {
Log.e(ContentValues.TAG, "[Error] Download PDV Fail --> $call")
}
})
return mutableLiveData
}
我返回数据下载以更新 UI,并通知用户下载了多少项目