You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin Clean Architecture中DTO映射及传入用例方法咨询

在Android Kotlin Clean Architecture中实现DTO映射并传入用例

Clean架构的核心是分层解耦,DTO(数据传输对象)属于数据层,而用例(UseCase)属于领域层——领域层绝对不能依赖数据层的模型,必须把DTO映射成领域层的Entity后,再传入用例处理。下面是具体实现步骤和代码示例:

1. 定义各层模型

数据层:DTO

对应接口返回的原始数据结构,仅负责数据传输,不包含任何业务逻辑:

// 数据层 - UserDTO.kt
data class UserDTO(
    val id: Int,
    val username: String,
    val email: String,
    val avatar_url: String
)

领域层:Entity

领域层的核心业务模型,属性命名和结构完全围绕业务需求设计,与数据层解耦:

// 领域层 - UserEntity.kt
data class UserEntity(
    val userId: Int,
    val userName: String,
    val userEmail: String,
    val avatarUrl: String
)

2. 实现DTO到Entity的映射

映射逻辑放在数据层(因为DTO属于数据层),推荐用Kotlin扩展函数,简洁直观:

// 数据层 - DtoMappers.kt
fun UserDTO.toEntity(): UserEntity {
    return UserEntity(
        userId = this.id,
        userName = this.username,
        userEmail = this.email,
        avatarUrl = this.avatar_url
    )
}

// 列表场景的扩展
fun List<UserDTO>.toEntityList(): List<UserEntity> = this.map { it.toEntity() }

如果映射逻辑复杂,也可以单独写映射器类:

class UserDtoMapper {
    fun mapToEntity(dto: UserDTO): UserEntity {
        return UserEntity(
            userId = dto.id,
            userName = dto.username,
            userEmail = dto.email,
            avatarUrl = dto.avatar_url
        )
    }
}

3. 数据层Repository完成映射并提供Entity

Repository是数据层和领域层的桥梁,负责获取DTO、映射成Entity,再暴露给领域层:

// 领域层 - UserRepository.kt(抽象接口,领域层定义)
interface UserRepository {
    suspend fun getUserById(userId: Int): UserEntity
}

// 数据层 - UserRepositoryImpl.kt(具体实现,数据层)
class UserRepositoryImpl(
    private val apiService: ApiService,
    // 若用映射器类则注入:private val mapper: UserDtoMapper
) : UserRepository {
    override suspend fun getUserById(userId: Int): UserEntity {
        val userDto = apiService.getUserById(userId)
        // 用扩展函数映射
        return userDto.toEntity()
        // 用映射器类则:return mapper.mapToEntity(userDto)
    }
}

4. 用例(UseCase)接收Entity处理业务

用例依赖领域层的Repository,直接操作Entity,完全不感知DTO的存在:

// 领域层 - GetUserByIdUseCase.kt
class GetUserByIdUseCase(
    private val userRepository: UserRepository
) {
    suspend operator fun invoke(userId: Int): UserEntity {
        // 可在此添加业务逻辑,比如参数校验
        require(userId > 0) { "用户ID必须为正数" }
        return userRepository.getUserById(userId)
    }
}

常见失败原因排查

  • 直接传DTO给用例:领域层不能依赖数据层模型,必须先映射成Entity,否则会打破分层原则,甚至编译报错。
  • 映射字段错误:检查DTO与Entity的字段映射是否匹配,比如拼写、类型是否一致。
  • 依赖注入问题:确保Repository实现类正确注入到用例,用例实例也正确提供给表现层(如ViewModel)。

完整流程示例

表现层(ViewModel)调用用例:

// 表现层 - UserViewModel.kt
class UserViewModel(
    private val getUserByIdUseCase: GetUserByIdUseCase
) : ViewModel() {
    fun fetchUser(userId: Int) {
        viewModelScope.launch {
            val userEntity = getUserByIdUseCase(userId)
            // 可选:将Entity映射成UI层的Model
            val userUiModel = userEntity.toUiModel()
            // 更新UI状态
        }
    }
}

内容的提问来源于stack exchange,提问作者Moaz Mamdouh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 19:45:29