Kotlin Android视图绑定:findViewById vs Butterknife vs Kotlin Android扩展
我试图找出在Kotlin中执行Android视图绑定的最佳方法。 似乎有几个选项在那里:
findViewById
val button: Button by lazy { findViewById<Button>(R.id.button) }
牛油刀
https://github.com/JakeWharton/butterknife
@BindView(R.id.button) lateinit var button: Button
Kotlin Android扩展
https://kotlinlang.org/docs/tutorials/android-plugin.html
import kotlinx.android.synthetic.main.activity_main.*
我非常熟悉Java领域的findViewById和Butterknife,但是Kotlin中每种视图绑定方法的优缺点是什么?
Kotlin Android扩展与RecyclerView + ViewHolder模式兼容吗?
另外Kotlin Android Extensions如何通过include
处理嵌套视图的视图绑定?
例如:对于使用activity_main.xml
的Activity,如何访问View custom1
?
activity_main.xml中
<...> <include layout="@layout/custom" android:id="@+id/custom" /> </>
custom.xml
<...> <View android:id="@+id/custom1" ... /> <View android:id="@+id/custom2" ... /> </>
kotlin-android-extensions
对Kotlin
更好。 黄油刀也很好,但kotlin-android-extensions
是一个更好,更聪明的选择。
原因 : Kotlin
使用synthetic
属性,并使用caching function
(因此轻微的快速活动/片段加载)按需调用,而ButterKnife
绑定所有视图在ButterKnife.bind()
(消耗略多的时间)。 使用Kotlin
您甚至不需要使用注释来绑定视图。
是的,它也与RecyclerView + ViewHolder模式很好,你只需要导入kotlinx.android.synthetic.main.layout_main.view.*
(如果layout_main.xml
是Activity / Fragment布局文件名)。
您不需要为使用include
导入的布局做任何额外的工作。 只需使用导入视图的ID。
看看下面的官方文档说明:
Kotlin Android Extensions是Kotlin编译器的一个插件,它有两件事:
- 在每个Kotlin活动中添加一个隐藏的缓存功能和一个字段。 该方法是相当小,所以它不会增加APK的大小。
用函数调用替换每个合成属性调用。
这是如何工作的,当调用合成属性时,接收者是模块源中的Kotlin Activity / Fragment类,调用缓存函数。 例如,给定
class MyActivity : Activity() fun MyActivity.a() { this.textView.setText(“”) }
在MyActivity内部生成一个隐藏的缓存函数,所以我们可以使用缓存机制。
但在以下情况下:
fun Activity.b() { this.textView.setText(“”) }
我们不知道这个函数是否只会被我们的来源的活动或简单的Java活动调用。 因此,即使前面例子中的MyActivity实例是接收者,我们也不会在那里使用缓存。
链接到上面的文档页面
我希望它有帮助。
我不能将这个问题标记为重复的,因为您提出了多个已经在不同问题下回答/讨论过的问题。
Kotlin中每个视图绑定方法的优缺点是什么?
这已经在这里讨论了 。
Kotlin Android Extensions如何通过include处理嵌套视图的视图绑定? 例如:对于使用activity_main.xml的Activity,如何访问View custom1?
所有Kotlin Android扩展都是为你调用findViewById
。 看到这里 。
Kotlin Android扩展与RecyclerView + ViewHolder模式兼容吗?
是的,它确实。 但是,您必须使用将从其获得的视图保存到属性中,因为在“活动”或“片段”中没有缓存。 看到这里 。
如果您仍然有未解答的问题,请随时要求澄清。
照顾使用
val button: Button by lazy { findViewById<Button>(R.id.button) }
当视图被破坏时,我已经面对这个问题,并且当你的片段的实例存活(我认为在活动的情况下它不适用),他们拥有引用旧视图的懒惰属性。
例:
你在布局中有一个静态值,比如说android:text="foo"
//calling first time override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { button.setText("bar") // button is called for the first time, // then button is the view created recently and shows "bar" }
然后碎片被破坏,因为你替换它,但是然后你回来,它再次呼叫onCreateView。
//calling second after destroyed override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { button.setText(Date().time.toString()) //button is already set, then you are setting the value the to old view reference // and in your new button the value won't be assigned // The text showed in the button will be "foo" }