MVVM协程问题

时间:2020-02-04 16:33:43

标签: android kotlin android-livedata coroutine

问题: 该代码仅在我刚启动应用程序或打开屏幕时才有效(据我了解,更改配置后,活动将再次绑定)。

然后我尝试发出请求,但对我来说不起作用。 在尽可能挂起Log之后,我意识到该代码未在resultLiveData的liveData()内部执行。 为什么会这样呢?以及如何解决?

有一个BaseRemoteSource负责从远程服务获取数据

abstract class BaseDataSource{

        public suspend fun <T> getResult(call : suspend () -> Response<T>) : Result<T>{
            try {
                //Получаем ответ от вызова
                val response = call()
                if(response.isSuccessful) {
                    //тело
                    val body = response.body()
                    if (body != null) return Result.success(body)
                }
                return error("${response.code()} ${response.message()} ${response.errorBody()}")
            }
            catch (e: Exception){
                Log.d("BaseDataSource", e.toString())
                return Result.error(e.message ?: e.toString())
            }
        }
    }

有一个继承人

class AlbumRemoteDataSource @Inject constructor(
    private val apiService: APIService
): BaseDataSource(){
    suspend fun getAlbumsBySearch(searchQuery: String): Result<AlbumsResponse>{
        val result = getResult{apiService.getAlbumsBySearch(searchQuery)}
        Log.d("AlbumRemoteDataSource", result.toString())
        return result
    }
}

在存储库中,我从远程服务获取数据,将其添加到数据库中,然后从中获取现成的数据集。

class AlbumRepository @Inject constructor(private val remoteSource: AlbumRemoteDataSource, private val database: AppDatabase){

    fun getAlbumsBySearch(searchQuery: String): LiveData<Result<List<Album>>>{

        Log.d("RepositoryNew", searchQuery)
        val resultLiveData = resultLiveData(
            databaseQuery = {database.getAlbumDao().getAlbumsBySearch("%${searchQuery}%")},
            networkCall = {remoteSource.getAlbumsBySearch(searchQuery)},
            saveCallResult = {database.getAlbumDao().insertAll(it.results)}
        )
        Log.d("AlbumRepository", resultLiveData.value.toString())
        return resultLiveData
    }
}

为此,我编写了resultLiveData

fun <T, A> resultLiveData(
databaseQuery: () -> LiveData<T>,
networkCall: suspend () -> Result<A>,
saveCallResult: suspend (A) -> Unit): LiveData<Result<T>>{
    Log.d("resultLiveData", "input")
 val news = liveData(Dispatchers.IO){


    emit(Result.loading<T>())
    val responseSource = networkCall.invoke()
    Log.d("ResultLiveData Network", responseSource.toString())
    if(responseSource.status == Result.Status.SUCCESS) {
        saveCallResult(responseSource.data!!)
        Log.d("resultLiveData", "save database")
    }
    else if(responseSource.status == Result.Status.ERROR){
        emit(Result.error(responseSource.error))
        Log.d("resultLiveData", "error ${responseSource.error}")
    }
    val databaseSource = databaseQuery.invoke()
    Log.d("ResultLiveData Database", databaseSource.value.toString())
    emitSource(databaseSource.map { Result.success(it) })
}
Log.d("resultLiveDataAll", news.toString())
return news

}

我想通过SearchView获取新数据。为此,我在ViewModel中调用hangleSearchQuery方法

private fun getAlbumsBySearch(searchQuery: String) = repository.getAlbumsBySearch(searchQuery)
fun handleSearchQuery(text: String?) {
    albums = getAlbumsBySearch(text.toString())
}

如果您查看日志,那么为什么它出现在resultLiveData中,而不进入liveData part()

日志

2020-02-04 19:18:06.522 5326-5326/ru.ddstudio.simpleitunesapp D/AlbumListViewModel SV: ryf
2020-02-04 19:18:06.964 5326-5326/ru.ddstudio.simpleitunesapp D/RepositoryNew: ryfh
2020-02-04 19:18:06.964 5326-5326/ru.ddstudio.simpleitunesapp D/resultLiveData: input
2020-02-04 19:18:06.965 5326-5326/ru.ddstudio.simpleitunesapp D/resultLiveDataAll: androidx.lifecycle.CoroutineLiveData@f0a4b27
2020-02-04 19:18:06.965 5326-5326/ru.ddstudio.simpleitunesapp D/AlbumRepository: null
2020-02-04 19:18:06.965 5326-5326/ru.ddstudio.simpleitunesapp D/AlbumListViewModel SV: ryfh
2020-02-04 19:18:07.174 5326-5326/ru.ddstudio.simpleitunesapp D/RepositoryNew: ryfhh
2020-02-04 19:18:07.175 5326-5326/ru.ddstudio.simpleitunesapp D/resultLiveData: input
2020-02-04 19:18:07.175 5326-5326/ru.ddstudio.simpleitunesapp D/resultLiveDataAll: androidx.lifecycle.CoroutineLiveData@17211d4
2020-02-04 19:18:07.175 5326-5326/ru.ddstudio.simpleitunesapp D/AlbumRepository: null

ViewModel

class AlbumListViewModel @Inject constructor(private val repository: AlbumRepository): ViewModel(){
private var albums : LiveData<Result<List<Album>>> = getAlbumsBySearch("")

private fun getAlbumsBySearch(searchQuery: String): LiveData<Result<List<Album>>>{
    return repository.getAlbumsBySearch(searchQuery)}

fun getAlbums(): LiveData<Result<List<Album>>>{
    Log.d("AlbumListViewModel", albums.value.toString())
    return albums
}
fun handleSearchQuery(text: String?) {
    albums = if (text != null){
        getAlbumsBySearch(text)
    } else{
        getAlbumsBySearch("")
    }
    Log.d("AlbumListViewModel SV", text.toString())
}

0 个答案:

没有答案