Проблемы MVVM Coroutine - PullRequest
       8

Проблемы MVVM Coroutine

0 голосов
/ 04 февраля 2020

Проблема: этот код работает только тогда, когда я только запустил приложение или когда я повернул экран (насколько я понимаю, при изменении конфигурации действие снова связывается).

Затем я пытаюсь сделать запрос, и он не работает для меня. Повесив журнал везде, где это возможно, я понял, что код не выполняется внутри liveData () в resultLiveData. Почему это происходит? и как это исправить?

Существует 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. Для этого я вызываю метод hangleSearchQuery в ViewModel

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

Если вы посмотрите журналы, то почему это в resultLiveData, а не go в части liveData ()

Log

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())
}
...