web-dev-qa-db-fra.com

Reliure Kotlin pour Android: extension de l'extension Android avec FindViewById vs Butterknife

J'essaie de trouver la meilleure façon de faire Android View Binding dans Kotlin. Il semble y avoir quelques options:

findViewById

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

Couteau à beurre

https://github.com/JakeWharton/butterknife

@BindView(R.id.button) lateinit var button: Button

Extensions Android Kotlin

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

import kotlinx.Android.synthetic.main.activity_main.*

Je connais assez bien findViewById et Butterknife en Java, mais quels sont les avantages et les inconvénients de chacune des approches de Kotlin? 

Les extensions Kotlin Android fonctionnent-elles bien avec le motif RecyclerView + ViewHolder?

Aussi, comment Kotlin Android Extensions gère-t-il la liaison de vues pour les vues imbriquées via include?

ex: pour une activité utilisant activity_main.xml, comment accéder à 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" ... />
</>
14
triad

kotlin-Android-extensions est préférable pour Kotlin. ButterKnife est également bon mais kotlin-Android-extensions est un choix meilleur et intelligent ici. 

Reason: Kotlin utilise synthetic propriétés. Celles-ci sont appelées à la demande à l'aide de caching function (d'où un léger chargement rapide d'Activités/Fragments) tandis que ButterKnife lie toutes les vues à la fois sur ButterKnife.bind() (qui consomme légèrement plus de temps). Avec Kotlin, vous n'avez même pas besoin d'utiliser une annotation pour lier les vues.

Oui, le motif RecyclerView + ViewHolder convient également. Il suffit d'importer kotlinx.Android.synthetic.main.layout_main.view.* (si layout_main.xml correspond au nom du fichier de mise en page Activité/Fragment).

Vous n'avez pas besoin de faire d'effort supplémentaire pour la présentation importée à l'aide de include. Il suffit d'utiliser l'identifiant des vues importées.

Consultez les notes de documentation officielles suivantes:

Kotlin Android Extensions est un plugin pour le compilateur Kotlin, et il fait deux choses:

  1. Ajoute une fonction de cache cachée et un champ à l'intérieur de chaque activité Kotlin. La méthode est plutôt petite, elle n'augmente donc pas beaucoup la taille de l'APK.
  2. Remplace chaque appel de propriété synthétique par un appel de fonction.

    Comment cela fonctionne? Lorsque vous appelez une propriété synthétique, où le destinataire est une classe Kotlin Activity/Fragment qui se trouve dans les sources du module, la fonction de mise en cache est appelée. Par exemple, étant donné

class MyActivity : Activity()
fun MyActivity.a() { 
    this.textView.setText(“”)
}

une fonction de mise en cache masquée est générée dans MyActivity, nous pouvons donc utiliser le mécanisme de mise en cache.

Cependant dans le cas suivant:

fun Activity.b() { 
    this.textView.setText(“”)
}

Nous ne saurions pas si cette fonction serait invoquée uniquement sur les activités de nos sources ou également sur les activités Java. En tant que tel, nous n’utilisons pas la mise en cache, même si l’instance MyActivity de l’exemple précédent est le destinataire.

Lien vers ci-dessus page de documentation

J'espère que ça aide.

12
chandil03

Prendre soin de l'utilisation

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

Je fais déjà face au problème lorsque la vue est détruite et, à mesure que l'instance de votre fragment survit (je pense que dans le cas d'activités, cela ne s'applique pas), ils tiennent la propriété lazy référençant à l'ancienne vue. 

Exemple:

Vous avez une valeur statique dans la présentation, disons 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"
}

Ensuite, le fragment est détruit parce que vous le remplacez, mais ensuite vous revenez et il a régénéré la callin onCreateView à nouveau.

//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"
}
4
crgarridos

Je ne peux pas signaler cette question comme un doublon, car vous posez plusieurs questions auxquelles il a été répondu/discuté sous différentes questions.

Quels sont les avantages et les inconvénients de chaque approche contraignante de vue dans Kotlin?

Cela a été discuté ici .

Comment Kotlin Android Extensions gère-t-il la liaison de vues pour les vues imbriquées via include? ex: pour une activité utilisant activity_main.xml, comment accéder à View custom1?

Toutes les extensions Kotlin Android font l’appel findViewById pour vous. Voir ici .

Les extensions Kotlin Android fonctionnent-elles bien avec le motif RecyclerView + ViewHolder?

Oui. Cependant, vous devez utiliser enregistrer les vues que vous en obtenez dans les propriétés, car elles ne disposent pas d'un cache, comme dans Activités ou Fragments. Voir ici .


Si vous avez toujours des questions sans réponse, n'hésitez pas à demander des éclaircissements.

4
zsmb13

si vous utilisez la bibliothèque de datainding. vous devez lier la vue à la liaison de données.

parce qu'il est plus explicite que les extensions kotlin

p.s findviewbyid est très gênant et code passe-partout

0
bong jae choe