Android中ViewModel传递UseCase:具体类与接口方案选型问询
Android Clean架构中ViewModel传递UseCase的两种方案选择
在Clean架构中,核心层是承载业务逻辑的UseCase层。在Android开发中,我们通常会将UseCase作为构造函数参数传递给ViewModel,示例代码如下:
class AddNoteUseCase(noteRepository: INoteRepository) : IUseCase { override fun invoke(note: Note) { noteRepository.addNote(note) } }
目前存在两种向ViewModel传递UseCase的实现方式:
1. UseCase与ViewModel紧耦合
class NoteViewModel(addNoteUseCase: AddNoteUseCase) { // 使用UseCase的业务代码 }
这种方案的问题很明显:无法伪造UseCase实例,导致ViewModel的单元测试难以隔离依赖;同时后续如果需要替换或扩展AddNoteUseCase的实现,ViewModel代码也必须跟着修改,不利于长期迭代。
2. UseCase与ViewModel松耦合
class NoteViewModel(addNoteUseCase: IUseCase) { // 使用UseCase的业务代码 }
这种方案通过依赖抽象接口IUseCase,支持伪造实例来完成ViewModel的单元测试,同时也更符合架构的扩展性要求。
哪种方案更实用?
针对这个问题存在两种不同观点:
- 观点一:UseCase仅包含单个方法,没必要伪造,直接依赖具体类更简单。
- 观点二:不伪造UseCase的话,无法完成相关测试。
实际开发中,松耦合方案更值得推荐,原因如下:
- 单元测试隔离性:ViewModel的单元测试核心是验证自身逻辑,而非UseCase的内部实现。通过伪造IUseCase,我们可以精准测试ViewModel是否在正确的时机、传入正确的参数调用了UseCase,完全不受UseCase依赖的Repository或其他组件影响,测试结果更可靠。
- 业务扩展性:当前的UseCase可能只有单个
invoke方法,但随着业务迭代,可能需要添加新方法,或者替换成其他实现(比如新增一个带缓存逻辑的AddNoteUseCase)。松耦合的方式让ViewModel无需修改任何代码就能适配这些变化,符合开闭原则。 - 契合Clean架构思想:Clean架构的核心原则之一是“依赖抽象,而非具体实现”,松耦合方案正是这一原则的落地,能让各层职责边界更清晰,代码的可维护性和可读性更强。
另外需要明确:UseCase本身的测试应该单独进行,测试时依赖其下层的抽象(比如示例中的INoteRepository)来伪造依赖,而非在ViewModel的测试中验证UseCase逻辑。ViewModel测试只需要确保正确调用了UseCase即可。
内容的提问来源于stack exchange,提问作者Shreyas Sparrow
相关产品推荐
相关产品推荐

