Kotlin中MVI模式下sealed类重复Toast副作用样板代码如何消除?
问题解答
1. sealed类是否可以继承其他sealed类
Kotlin 1.5及以上版本支持该特性:父sealed类的构造函数默认是protected权限,允许另一个sealed类作为子类继承,要求父sealed类的所有直接子类必须和父类处于同一模块、同一包名下。Kotlin 1.5之前的版本不支持sealed类之间的继承。
2. 消除Toast等通用副作用样板代码的方案
推荐方案:抽取公共sealed父类
和你抽取BaseMviState接口的思路一致,把所有模块通用的副作用统一放到父sealed类中,各业务模块的副作用sealed类直接继承该父类即可,无需重复定义通用副作用:
// 公共父副作用类,统一存放通用逻辑 sealed class BaseMviSideEffect { data class Toast(val message: String) : BaseMviSideEffect() // 可扩展其他通用副作用,比如页面跳转、关闭页面等 data class NavigateTo(val targetClazz: Class<*>) : BaseMviSideEffect() object CloseCurrentPage : BaseMviSideEffect() } // 业务模块副作用直接继承即可,无需重复写Toast sealed class MviJoinSideEffect : BaseMviSideEffect() { data class SetupAutoLogin(val user: User) : MviJoinSideEffect() } sealed class MviRoomCreateSideEffect : BaseMviSideEffect() { // 业务独有的副作用写在这里即可 }
使用时直接在副作用处理逻辑中统一匹配通用副作用即可:
fun handleSideEffect(effect: BaseMviSideEffect) { when(effect) { is BaseMviSideEffect.Toast -> showToast(effect.message) is BaseMviSideEffect.NavigateTo -> startActivity(Intent(this, effect.targetClazz)) is MviJoinSideEffect.SetupAutoLogin -> handleAutoLogin(effect.user) // 其他业务副作用匹配 } }
兼容旧版本Kotlin的方案
如果你的项目使用的Kotlin版本低于1.5,无法使用sealed类继承特性,可以用组合包装的方式实现通用副作用复用:
// 通用副作用定义 sealed class CommonSideEffect { data class Toast(val message: String) : CommonSideEffect() } // 业务侧副作用分通用、业务两类包装 sealed class MviJoinSideEffect { data class Biz(val effect: MviJoinBizEffect) : MviJoinSideEffect() data class Common(val effect: CommonSideEffect) : MviJoinSideEffect() } // 业务独有的副作用定义在这里 sealed class MviJoinBizEffect { data class SetupAutoLogin(val user: User) : MviJoinBizEffect() }
发送Toast副作用时使用MviJoinSideEffect.Common(CommonSideEffect.Toast("提示内容"))即可,无需每个业务模块重复定义Toast类。
内容的提问来源于stack exchange,提问作者Ji Sungbin
相关产品推荐
相关产品推荐

