Не удается вызвать источник данных из репозитория

#android #kotlin-coroutines

#Android #kotlin-сопрограммы

Вопрос:

Я хочу получить данные из источника данных. Но, оказывается, он вообще не выполнялся. Как я могу это решить? вот мой код

Repository.kt

     // all logcat in repository is executed
    override fun getDetailGame(id: Int): Flow<Resource<Game>> {
        Log.d("Repo", "getDetailGame: called")
        return flow {
            Log.d("Repo", "getDetailGame: before flow")
            remoteDataSource.getDetailGame(id)
            Log.d("Repo", "getDetailGame: after flow")
        }
    }
 

Datasource.kt

 suspend fun getDetailGame(id: Int): Flow<ApiResponse<GameResponse>> =
    flow {
        try {
            // didnt get executed all
            Log.d(TAG, "getDetailGame: called")
            val response = apiService.getDetailGame(id)
            if (response != null) {
                emit(ApiResponse.Success(response))
            } else {
                emit(ApiResponse.Empty)
            }
        } catch (ex: Exception) {
            emit(ApiResponse.Error(ex.message.toString()))
            Log.e(TAG, "getDetailGame: ${ex.message} ")
        }
    }.flowOn(Dispatchers.IO)
 

Редактировать: добавить дополнительный код для другого файла

ApiResponse.kt (управление состоянием ответа для источника данных)

 sealed class ApiResponse<out R> {
    data class Success<out T>(val data: T) : ApiResponse<T>()
    data class Error(val errorMessage: String) : ApiResponse<Nothing>()
    object Empty : ApiResponse<Nothing>()
}
 

Resource.kt (управление состоянием пользовательского интерфейса, например, состояние загрузки и т. Д.)

 sealed class Resource<T>(val data: T? = null, val message: String? = null) {
    class Success<T>(data: T) : Resource<T>(data)
    class Loading<T>(data: T? = null) : Resource<T>(data)
    class Error<T>(message: String, data: T? = null) : Resource<T>(data, message)
}
 

GameResponse.kt (то же, что и Game, но с serializedname для json)

 data class GameResponse(
    @field:SerializedName("id")
    var id: Int,

    @field:SerializedName("name")
    var title: String,

    @field:SerializedName("released")
    var released: String? = null,

    @field:SerializedName("metacritic")
    var metacritic: Int? = null,

    @field:SerializedName("metacritic_url")
    var metacriticUrl: Int? = null,

    @field:SerializedName("background_image")
    var bgImage: String? = null,

    @field:SerializedName("description")
    var description: String? = null,

    @field:SerializedName("game_series_count")
    var gameSeriesCount: Int? = 0
)
 

Game.kt (такой же, как GameResponse, но его чистая версия)

 data class Game(
    var id: Int,
    var title: String,
    var released: String? = null,
    var metacritic: Int? = null,
    var metacriticUrl: Int? = null,
    var bgImage: String? = null,
    var description: String? = null,
    var gameSeriesCount: Int? = 0
)
 

Ответ №1:

Потоки — это холодные потоки, это означает, что они не будут выполняться, пока вы их не соберете. Если вы пытаетесь преобразовать Flow<ApiResponse> в Flow<Resource> , вам следует использовать map функцию. Если вам нужно более сложное преобразование, используйте transform вместо этого.

 override fun getDetailGame(id: Int): Flow<Resource<GameResponse>> {
    return remoteDataSource.getDetailGame(id).map { response ->
        when (response) {
            ApiResponse.Empty -> Resource.Loading()
            is ApiResponse.Success -> Resource.Success(response.data)
            is ApiResponse.Error -> Resource.Error(response.errorMessage)
        }
    }
}
 

Или, если вам нужно передать значение перед выполнением преобразования:

 override fun getDetailGame(id: Int): Flow<Resource<GameResponse>> = flow {
    emit(Resource.Loading())
    emitAll(
        remoteDataSource.getDetailGame(id).map { response ->
            when (response) {
                is ApiResponse.Success -> Resource.Success(response.data)
                is ApiResponse.Error -> Resource.Error(response.errorMessage)
                ApiResponse.Empty -> Resource.Error("")
            }
        }
    )
}
 

Комментарии:

1. Любая ссылка на то, как выполнить преобразование?

2. Я не знаю, что вы пытаетесь сделать, и для того, чтобы помочь вам, мне нужно увидеть эти классы: ApiResponse, GameResponse, Resource, Game

3. ApiResponse и Resource — это закрытый класс для управления состоянием. Game и GameResponse — это один и тот же класс данных, GameResponse имеет serializedname для извлечения ключа из JSON и отобразит его в классе игровых данных. Все свойства обоих классов одинаковы.

4. можете ли вы добавить их в свой вопрос?

5. добавлено к сообщению сэр