跳到主要内容

UseCase 用例

问题

UseCase(用例)在 Android 架构中是什么?何时需要引入?

答案

UseCase 是什么

UseCase 是 Domain 层的核心组件,封装单一业务逻辑,协调多个 Repository:

基础实现

// 定义基类,统一调用方式
abstract class UseCase<in P, out R> {
abstract suspend operator fun invoke(params: P): R
}

abstract class FlowUseCase<in P, out R> {
abstract operator fun invoke(params: P): Flow<R>
}
// 具体用例:获取文章列表(合并用户收藏状态)
class GetArticlesUseCase(
private val articleRepo: ArticleRepository,
private val userRepo: UserRepository
) : FlowUseCase<Unit, List<ArticleUiModel>>() {

override fun invoke(params: Unit): Flow<List<ArticleUiModel>> {
// 组合两个数据源
return combine(
articleRepo.observeArticles(),
userRepo.observeFavorites()
) { articles, favorites ->
articles.map { article ->
ArticleUiModel(
id = article.id,
title = article.title,
isFavorite = article.id in favorites
)
}
}
}
}

在 ViewModel 中使用

@HiltViewModel
class ArticleViewModel @Inject constructor(
private val getArticles: GetArticlesUseCase,
private val toggleFavorite: ToggleFavoriteUseCase
) : ViewModel() {

val articles = getArticles(Unit)
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())

fun onFavoriteClick(articleId: String) {
viewModelScope.launch {
toggleFavorite(articleId)
}
}
}

何时需要 UseCase

场景是否需要 UseCase
直接透传 Repository 数据❌ 过度封装
组合多个 Repository 数据✅ 适合
包含业务规则(排序、过滤、转换)✅ 适合
多个 ViewModel 共享相同逻辑✅ 适合
不要过度使用

如果 UseCase 只是 repository.getData() 的透传包装,没有额外逻辑,就不需要引入 UseCase。只在有明确业务逻辑需要封装时才使用


常见面试问题

Q1: UseCase 应该只有一个公开方法吗?

答案

是的。遵循单一职责原则,每个 UseCase 只有一个 invoke 方法(通过 operator fun invoke 实现简洁调用)。如果需要多个操作,应拆分成多个 UseCase。

Q2: UseCase 和 Repository 有什么区别?

答案

  • Repository:数据层,关注数据怎么获取和存储(API、数据库、缓存)
  • UseCase:领域层,关注业务逻辑(组合数据、业务规则、数据转换)

Repository 是按数据实体划分(UserRepositoryArticleRepository),UseCase 是按业务场景划分(GetArticleWithFavoriteUseCaseLoginUseCase)。

相关链接