无法从存储库调用数据源

Can Not Call Datasource from Repository

我想从数据源中检索数据。但事实证明它根本没有被执行。我该如何解决?这是我的代码

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(UI 的状态管理,如加载状态等)

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 相同,但序列化名称为 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
)

流是冷流,这意味着在您收集它们之前它们不会被执行。 如果您尝试将 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("")
            }
        }
    )
}