Clean MVVM 架构中的 API 响应处理

问题描述 投票:0回答:1

我已经使用 Clean Architecture 构建了应用程序,现在我计划在其中添加网络层验证。

下面是我如何在我的应用程序中实现此功能的代码。

interface JokeApi {
    @GET("joke/Any")
    suspend fun getJoke(): Response<JokeResponseDto>
}
class JokeRepositoryImpl @Inject constructor(private val jokeApi: JokeApi) : JokeRepository {
    override suspend fun getJoke(): NetworkResponse<JokeResponse> {
        return handleApiResponse { jokeApi.getJoke() }
    }
}
  • handleApiResponse 函数返回类型为
    NetworkResponse<JokeResponseDto>
suspend fun <T> handleApiResponse(execute: suspend () -> Response<T>): NetworkResponse<T> {
    return try {
        val response = execute()
        val body = response.body()
        if (response.isSuccessful && body != null) {
            NetworkResponse.Success(data = body)
        } else {
            NetworkResponse.Error(errorMessage = response.message())
        }
    } catch (exception: HttpException) {
        NetworkResponse.Error(errorMessage = exception.localizedMessage)
    } catch (throwable: Throwable) {
        NetworkResponse.Exception(throwable = throwable)
    }
}
sealed class NetworkResponse<T>(
    val data: T? = null,
    val errorMessage: String? = null,
    val exception: Throwable? = null,
) {
    class Success<T>(data: T) : NetworkResponse<T>(data = data)
    class Error<T>(errorMessage: String?) : NetworkResponse<T>(errorMessage = errorMessage)
    class Exception<T>(throwable: Throwable) : NetworkResponse<T>(exception = throwable)
}

这里的问题是,retrofit 返回

JokeResponseDto
响应对象,而
getJoke
JokeRepositoryImpl
函数期望
JokeResponse
在此代码中的情况下是有效的
mapping
功能缺失。

我自己尝试在handleApiResponse方法中添加映射,因为它是通用类型,所以没有太多考虑实现。

下面是我如何尝试将响应转换为另一个对象,仅包含必要的详细信息。

class JokeResponseMapper : Mapper<JokeResponseDto, JokeResponse> {
    override fun mapFrom(from: JokeResponseDto): JokeResponse {
        return JokeResponse(
            error = from.error,
            type = from.type.orEmpty(),
            setUp = from.type,
            joke = from.joke,
        )
    }
}
interface Mapper<F, T> {
    fun mapFrom(from: F): T
}

任何有关代码的帮助将不胜感激。

android kotlin generics repository-pattern clean-architecture
1个回答
0
投票

您可以创建一个将响应对象映射到域模型的接口:

interface DomainModel<T> {
fun mapToDomain(): T

}

然后像这样更改handleApiResponse:

suspend fun <DomainModel> handleApiResponse(execute: suspend () -> Response<DomainModel>): NetworkResponse<DomainModel> {
return try {
    val response = execute()
    val body = response.body()
    if (response.isSuccessful && body != null) {
        NetworkResponse.Success(data = body.mapToDomain())
    } else {
        NetworkResponse.Error(errorMessage = response.message())
    }
} catch (exception: HttpException) {
    NetworkResponse.Error(errorMessage = exception.localizedMessage)
} catch (throwable: Throwable) {
    NetworkResponse.Exception(throwable = throwable)
}

}

现在 JokeResponseDto 必须实现这个接口,并且您必须在其中实现 mapToDomain 函数。

例如:

class JokeResponseDto(
    ....
    .... 
): DomainModel<JokeResponse> {
     override fun mapToDomain(): JokeResponse {
          return JokeResponse(
              ...
          )
     }
© www.soinside.com 2019 - 2024. All rights reserved.