如何实现适配Android ActionCallback的无参构造通用基类
问题
我有4个继承自ActionCallback的类,代码逻辑高度相似,仅在运行时需实例化不同的Object(ObjectA-D)与MyClass(MyClassA-D)。原本可通过传参创建对应对象与类,但受Android ActionCallback特性限制,无法向Action类传递参数。现希望实现类似GenericAction的通用基类,作为单一可信源,避免重复编写4个Action类,请教最优实现方式。
原重复代码示例:
class ActionA : ActionCallback { override suspend fun onAction(context: Context, glanceId: GlanceId, parameters: ActionParameters) { doSomething(context, ObjectA, glanceId) val constructSomething = MyClassA(context) } } class ActionB : ActionCallback { override suspend fun onAction(context: Context, glanceId: GlanceId, parameters: ActionParameters) { doSomething(context, ObjectB, glanceId) val constructSomething = MyClassB(context) } } class ActionC : ActionCallback { override suspend fun onAction(context: Context, glanceId: GlanceId, parameters: ActionParameters) { doSomething(context, ObjectC, glanceId) val constructSomething = MyClassC(context) } } class ActionD : ActionCallback { override suspend fun onAction(context: Context, glanceId: GlanceId, parameters: ActionParameters) { doSomething(context, ObjectD, glanceId) val constructSomething = MyClassD(context) } }
尝试的通用类(存在实例化参数问题):
class GenericAction<T>(myObject: Any, myClazz: Class<T>) : ActionCallback { override suspend fun onAction(context: Context, glanceId: GlanceId, parameters: ActionParameters) { doSomething(context, myObject, glanceId) val constructSomething = myClazz<T>(context) } }
最优实现方案
方案1:枚举封装+泛型基类(类型安全首选)
因为Android要求ActionCallback必须有无参构造,我们可以用枚举封装每个Action需要的依赖逻辑,再通过静态内部类实现无参构造的要求,同时把核心逻辑统一到基类中。
步骤1:统一基类与枚举定义
先给MyClassA-D定义共同基类,再用枚举封装每个Action的专属依赖:
// 给MyClass系列定义抽象基类,统一类型 abstract class BaseMyClass(context: Context) class MyClassA(context: Context) : BaseMyClass(context) class MyClassB(context: Context) : BaseMyClass(context) class MyClassC(context: Context) : BaseMyClass(context) class MyClassD(context: Context) : BaseMyClass(context) // 枚举封装每个Action需要的Object对象和MyClass构造逻辑 enum class ActionType( val targetObject: Any, val myClassCreator: (Context) -> BaseMyClass ) { TYPE_A(ObjectA) { context -> MyClassA(context) }, TYPE_B(ObjectB) { context -> MyClassB(context) }, TYPE_C(ObjectC) { context -> MyClassC(context) }, TYPE_D(ObjectD) { context -> MyClassD(context) } }
步骤2:实现通用ActionCallback基类
通过私有构造+静态内部类的方式,满足Android无参构造要求,同时复用核心逻辑:
class GenericAction private constructor(private val actionType: ActionType) : ActionCallback { override suspend fun onAction(context: Context, glanceId: GlanceId, parameters: ActionParameters) { // 复用共同逻辑 doSomething(context, actionType.targetObject, glanceId) val constructSomething = actionType.myClassCreator(context) // 后续可统一处理constructSomething的逻辑 } // 为每个ActionType生成无参子类,直接用于Android组件绑定 class ActionA : GenericAction(ActionType.TYPE_A) class ActionB : GenericAction(ActionType.TYPE_B) class ActionC : GenericAction(ActionType.TYPE_C) class ActionD : GenericAction(ActionType.TYPE_D) }
使用时直接引用GenericAction.ActionA、GenericAction.ActionB即可,后续新增类型只需在枚举中添加项,再新增一个对应静态内部类,完全避免重复代码。
方案2:ActionParameters传递标识(动态场景可选)
如果允许在触发Action时传递参数,可以通过ActionParameters传入类型标识,在通用Action中分支处理:
class GenericAction : ActionCallback { override suspend fun onAction(context: Context, glanceId: GlanceId, parameters: ActionParameters) { val actionType = parameters[KEY_ACTION_TYPE] ?: return // 获取对应Object val targetObject = when(actionType) { "TYPE_A" -> ObjectA "TYPE_B" -> ObjectB "TYPE_C" -> ObjectC "TYPE_D" -> ObjectD else -> return } doSomething(context, targetObject, glanceId) // 实例化对应MyClass val constructSomething = when(actionType) { "TYPE_A" -> MyClassA(context) "TYPE_B" -> MyClassB(context) "TYPE_C" -> MyClassC(context) "TYPE_D" -> MyClassD(context) else -> return } // 后续逻辑 } companion object { val KEY_ACTION_TYPE = ActionParameters.Key<String>("action_type") // 触发Action时传入参数:actionParametersOf(KEY_ACTION_TYPE to "TYPE_A") } }
这种方式无需创建多个子类,但依赖参数传递,类型安全稍弱,适合类型可能动态调整的场景。
方案对比
- 方案1:类型安全、代码整洁,维护成本低,适合类型固定、不频繁新增的场景。
- 方案2:无需多子类,灵活性高,但类型校验依赖运行时,适合动态场景。
内容的提问来源于stack exchange,提问作者mars8
相关产品推荐
相关产品推荐

