Kotlin Android View Binding: findViewById vs Butterknife vs Kotlin Android Extension

Я пытаюсь найти лучший способ сделать Android View Binding в Kotlin. Кажется, есть несколько вариантов:

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 Extensions

https://kotlinlang.org/docs/tutorials/android-plugin.html

 import kotlinx.android.synthetic.main.activity_main.* 

Я хорошо знаком с findViewById и Butterknife в java land, но каковы плюсы и минусы каждого подхода к привязке каждого взгляда в Котлине?

Расширяется ли Kotlin Android Extensions с шаблоном RecyclerView + ViewHolder?

Также как Kotlin Android Extensions обрабатывает привязку вида для вложенных представлений через include ?

ex: для Activity, использующего activity_main.xml , как можно было бы 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 . ButterKnife также хорош, но 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 . Просто используйте идентификатор импортированных представлений.

    Взгляните на следующие официальные документы:

    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 Android Extensions обрабатывает привязку вида для вложенных представлений через include? ex: для Activity, использующего activity_main.xml, как можно было бы просмотреть пользовательский интерфейс1?

    Все Kotlin Android Extensions – это вызов findViewById для вас. См. Здесь .

    Расширяется ли Kotlin Android Extensions с шаблоном RecyclerView + ViewHolder?

    Да. Тем не менее, вы должны использовать сохранение Представлений, которые вы получаете от него, в свойствах, поскольку для них нет кеша, например, в «Действиях или фрагментах». См. Здесь .


    Если у вас остались нерешенные вопросы, не стесняйтесь просить разъяснений.

    Позаботьтесь об использовании

     val button: Button by lazy { findViewById<Button>(R.id.button) } 

    Я уже сталкиваюсь с проблемой, когда представление уничтожается, и поскольку экземпляр вашего фрагмента выживает (я думаю, что в случае acitivities он не применяется), они содержат ленивое свойство, ссылающееся на старое представление.

    Пример:

    У вас статическое значение в макете, скажем, 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" } 

    Затем фрагмент уничтожается, потому что вы его заменяете, но затем возвращаетесь обратно и снова восстанавливаете callin 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" }