前言
委托(Delegation)是一种强大的特性,它允许一个类将某些责任(例如属性的存储或方法的实现)委托给另一个对象。委托有助于减少重复代码,并使代码更加清晰和模块化。
何时使用委托
以下是一些适合使用委托的场景:
1. 属性委托:当多个属性有相似的行为或存储需求时,可以使用属性委托来避免重复代码。例如,你可以使用 by lazy
委托来确保属性只被初始化一次,或者使用 observable
委托来监听属性的变化。
kotlinval lazyValue: String by lazy {
computeHeavyValue()
}
var observableValue: Int by Delegates.observable(0) { prop, oldValue, newValue ->
println("$prop changed from $oldValue to $newValue")
}
2. 方法委托:当你想将一个类的方法实现委托给另一个对象时,可以使用方法委托。这有助于保持代码的 DRY(Don't Repeat Yourself)原则,并使代码更加模块化。
kotlinclass DelegatingClass(private val delegate: AnotherClass) : AnotherClass by delegate
3. 接口实现委托:如果一个类需要实现多个接口,并且其中一些接口的方法实现是相似的,那么可以使用接口实现委托来减少重复代码。
kotlininterface BaseInterface {
fun commonMethod()
}
class ImplementingClass : BaseInterface by object : BaseInterface {
override fun commonMethod() {
println("Common method implementation")
}
}
一、使用委托类来实现多继承
interface CanFly {
fun fly()
}
interface CanEat {
fun eat()
}
open class Flyer : CanFly {
override fun fly() {
println("I can fly")
}
}
open class Animal : CanEat {
override fun eat() {
println("I can eat")
}
}
class Bird(flyer: Flyer, animal: Animal) : CanFly by flyer, CanEat by animal { }
fun main() {
val flyer = Flyer()
val animal = Animal()
val b = Bird(flyer, animal)
b.fly()
b.eat()
}
二、使用委托类来创建viewmodel实例
private lateinit var intoCabinetViewModel: IntoCabinetViewModel
// 然后在oncreat里面进行初始化
intoCabinetViewModel = ViewModelProvider(this)[IntoCabinetViewModel::class.java]
这种方式的写法存在未初始化的crash风险,所以我们可以使用委托来实现viewmodel的实例:
private val mViewModel by viewModels<MainViewModel>()
需要引入:
implementation 'androidx.activity:activity-ktx:1.7.1'//viewModels
三、使用委托把activity的部分职责代码分离出来
示例代码如下:
MainActivity :
class MainActivity : AppCompatActivity(), DeepLinkHandler by DeepLinkHandlerImpl() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
handleDeepLink(this, intent)
}
}
interface DeepLinkHandler {
fun handleDeepLink(activity: Activity, intent: Intent?)
}
class DeepLinkHandlerImpl : DeepLinkHandler {
override fun handleDeepLink(activity: Activity, intent: Intent?) {
Log.e("TAG", "开始处理handleDeepLink")
}
}
运行之后,就能够看到日志:开始处理handleDeepLink