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-extensionsKotlin更好。 黄油刀也很好,但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编译器的一个插件,它有两件事:

  1. 在每个Kotlin活动中添加一个隐藏的缓存功能和一个字段。 该方法是相当小,所以它不会增加APK的大小。
  2. 用函数调用替换每个合成属性调用。

    这是如何工作的,当调用合成属性时,接收者是模块源中的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" }