通过 Kotlin 中的两个接口:ReadOnlyProperty 和 ReadWriteProperty,可以方便的实现属性委托或局部委托。对于 val 变量使用 ReadOnlyProperty,而 var 变量实现ReadWriteProperty。
这里通过 kotlin 实现委托获取界面跳转时 intent 传递的数据:
fun <T> extraActivity(name: String): ActivityExtras<T?> = ActivityExtras(name, null)
fun <T> extraActivity(name: String, defaultValue: T) = ActivityExtras(name, defaultValue)
fun <T> extraFragment(name: String): FragmentExtras<T?> = FragmentExtras(name, null)
fun <T> extraFragment(name: String, defaultValue: T) = FragmentExtras(name, defaultValue)
class ActivityExtras<T>(private val name: String, private val defaultValue: T) :
ReadOnlyProperty<Activity, T> {
private var extra: T? = null
override fun getValue(thisRef: Activity, property: KProperty<*>): T {
return extra
?: thisRef.intent?.extras?.take<T>(name)?.also { extra = it }
?: defaultValue.also { extra = it }
}
}
class FragmentExtras<T>(private val name: String, private val defaultValue: T) :
ReadOnlyProperty<Fragment, T> {
private var extra: T? = null
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
return extra
?: thisRef.arguments?.take<T>(name)?.also { extra = it }
?: defaultValue.also { extra = it }
}
}
@Suppress("UNCHECKED_CAST")
fun <T> Bundle.take(key: String): T? {
try {
return get(key) as? T?
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
使用姿势:
// 跳转至 activity
val intent = Intent(context, xxx::class.java)
intent.putExtra("name", "candy")
context.startActivity(intent)
// activity 中获取参数
private val mName by extraActivity<String>("name")
// fragment 传递参数
val fragment = XxxFragment()
fragment.arguments = Bundle().apply { putString("name", name) }
// fragment 中获取参数
private val mName by extraFragment<String>("name")
就这么简单。