[英]how to properly use kotlin delegate to create bundle
Trying to create some shortcut to simplify legacy code.尝试创建一些快捷方式来简化遗留代码。 Here how fragments are instantiated:这里片段是如何实例化的:
CustomFragmentManager.showFragment(
Car::class.java.name,
Car.createBundle(
Color.Red
"modelaName",
4,
),
context
)
The showFragment is the legacy code whose signature I can't change: showFragment(String className, Bundle args, Context context) showFragment 是我无法更改其签名的遗留代码: showFragment(String className, Bundle args, Context context)
Inside the Car fragment:汽车片段内部:
private var color: ColorEnum by argument()
private var modelName: String? by argumentNullable()
private var cylinders: Int by argument()
companion object {
@JvmStatic
fun newInstance(
color: ColorEnum,
modelName: String? = null,
cylinders: Int = -1,
) = Car().apply {
this.color: color,
this.modelName: modelName,
this.cylinders: cylinders,
}
@JvmStatic
fun createBundle(
color: ColorEnum,
modelName: String? = null,
cylinders: Int = -1,
) = Bundle().apply {
putSerializable(ARG_1, color)
putString(ARG_2, modelName)
putInt(ARG_3, cylinders)
}
I took inspiration from this nice article ( https://proandroiddev.com/kotlin-delegates-in-android-1ab0a715762d ) to create the delegates and get rid of the ARGS stuff in the newIntance.我从这篇好文章 ( https://proandroiddev.com/kotlin-delegates-in-android-1ab0a715762d ) 中获得灵感来创建代表并摆脱 newIntance 中的 ARGS 内容。 Is there a way to simplify also the createBundle and definitely remove all these ARGS?有没有办法简化 createBundle 并明确删除所有这些 ARGS?
To use the names of the properties as keys like that delegate does, you can create an extension function that uses a property to call through to the other extension function Bundle.put()
that the article you linked describes.要将属性的名称用作该委托的键,您可以创建一个扩展 function,该扩展使用属性调用您链接的文章描述的另一个扩展 function Bundle.put()
。
fun Bundle.putPropertyByName(property: KProperty0<*>) = put(property.name, property.get())
KProperty0
means you don't separately have to pass an instance of the class that has the property to be able to get()
its value. KProperty0
意味着您不必单独传递具有能够get()
其值的属性的 class 的实例。 When you pass member properties of your Fragment to this function, the Fragment instance will be bound to the property object.当您将 Fragment 的成员属性传递给此 function 时,Fragment 实例将绑定到属性 object。
Call it by passing properties this way:通过以这种方式传递属性来调用它:
Bundle().apply {
putPropertyByName(::color)
putPropertyByName(::modelName)
putPropertyByName(::cylinders)
}
Or make a helper function to simplify:或者制作一个助手 function 来简化:
fun bundleOfProperties(vararg properties: KProperty0<*>): Bundle = Bundle(properties.size).apply {
properties.forEach(::putPropertyByName)
}
//...
fun createBundle(
color: ColorEnum,
modelName: String? = null,
cylinders: Int = -1,
) = bundleOfProperties(::color, ::modelName, ::cylinders)
Also, I think that function Bundle.get()
from the article needs to have a case added at the top for null
values or it will reach the else
clause on null values.另外,我认为文章中的 function Bundle.get()
需要在null
值的顶部添加一个案例,否则它将到达 null 值的else
子句。
fun <T> Bundle.put(key: String, value: T) {
when (value) {
is null -> putString(key, null)
is Boolean -> putBoolean(key, value)
is String -> putString(key, value)
is Int -> putInt(key, value)
//...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.