我刚入行 Android 开发的时候,还没有 Fragments, RecyclerViews, ViewModels, 和 Coroutines(协程)。技术组件更新换代,但是唯一不变的是:BaseClass,存在于项目中的各种基类?。
如果你没有见过 BaseActivity, BaseFragment 或者 BaseViewModel ,那你一定是幸运的?。
这些 BaseClass 基类对 “ (Don’t Repeat Yourself)禁止重复 ”这一原则的错误应用。
“Don’t repeat yourself” (DRY) 是软件开发中的一个原则,旨在使用抽象和数据标准化来减少软件开发中的重复工作。
一个常见的场景:当你需要在你的 App 中做追踪日志分析,或者需要在每个 Acticity 中注册一个 BroadcastReceiver 来发通知。
class BaseActivity: AppCompatActivity() {
private lateinit var logoutReceiver: BroadcastReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
logoutReceiver = LogoutReceiver()
registerReceiver(logoutReceiver, IntentFilter("ACTION_LOGOUT"))
}
override fun onStart() {
super.onStart()
traceEvent("Activity started")
}
override fun onStop() {
traceEvent("Activity stopped")
super.onStop()
}
private fun traceEvent(event: String) {
//MyAnalytics.newEvent(event)
}
inner class LogoutReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
finish()
}
}
}
复制代码
上述代码看起来没啥问题,每个继承 BaseActivity 的子类不需要新写代码,通过继承具备了父类追踪日志和退出登录的能力。
但是不是每个 Activity 我都需要追踪日志和退出登录,对于这些 Activity 这两个功能就是多余的。
有人说我可以通过一个 flag 标记这两个功能是否开启,这是错误❌的做法。
我们可以使用委托模式( Delegation ) ,利用 Kotlin(Java 也可以,需要写一些额外的代码)和 Android Lifecycle 组件的摆脱 BaseClass 这个噩梦。
委托模式(delegation pattern) 是 软件设计模式 中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如 状态模式 、 策略模式 、 访问者模式 本质上是在更特殊的场合采用了委托模式。委托模式使得我们可以用 聚合 来替代 继承 ,它还使我们可以模拟 mixin 。——维基百科
我们可以创建一个接口,将实际实现交给委托类。得益于 Lifecycle 组件,我们可以将我们的逻辑和生命周期绑定。
我们只需要 2 步:
- 为每一个 Feature 创建它的接口和实现类。(遵循单一职责的原则)
- Activity/Fragment 实现接口,将接口的实现交给委托的实现类并且绑定 lifecycle 的生命周期
class MyActivity:
AppCompatActivity(),
AnalyticsDelegate by AnalyticsDelegateImpl(),
LogoutDelegate by LogoutDelegateImpl()
{
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
registerAnalytics(lifecycle)
registerLogout(this)
}
}
复制代码
接口和委托实现类:
interface AnalyticsDelegate {
fun registerAnalytics(lifecycle: Lifecycle)
}
class AnalyticsDelegateImpl: AnalyticsDelegate, DefaultLifecycleObserver {
override fun registerAnalytics(lifecycle: Lifecycle) {
lifecycle.addObserver(this)
}
override fun onStart(owner: LifecycleOwner) {
traceEvent("Activity started")
}
override fun onStop(owner: LifecycleOwner) {
traceEvent("Activity stopped")
}
private fun traceEvent(event: String) {
//MyAnalytics.newEvent(event)
}
}
复制代码
interface LogoutDelegate {
fun registerLogout(activity: AppCompatActivity)
}
class LogoutDelegateImpl: LogoutDelegate, DefaultLifecycleObserver {
private lateinit var activity: AppCompatActivity
override fun registerLogout(activity: AppCompatActivity) {
this.activity = activity
this.activity.lifecycle.addObserver(this)
}
private lateinit var logoutReceiver: BroadcastReceiver
override fun onCreate(owner: LifecycleOwner) {
logoutReceiver = LogoutReceiver()
activity.registerReceiver(logoutReceiver, IntentFilter("ACTION_LOGOUT"))
//unregister missing for keeping the sample code smaller!
}
inner class LogoutReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
activity.finish()
}
}
}
复制代码
你有使用过委托模式吗?在评论中告诉我你有没有被 BaseActivity 折磨过!?