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 是按数据实体划分(UserRepository、ArticleRepository),UseCase 是按业务场景划分(GetArticleWithFavoriteUseCase、LoginUseCase)。