web-dev-qa-db-fra.com

Kotlin attribut personnalisé databinding

J'essaie de définir un attribut personnalisé à l'aide de Android DataBinding Library dans mon projet Kotlin, comme suit:

Disposition

<ImageView
    Android:id="@+id/imgView”
    Android:layout_width="40dp"
    Android:layout_height="40dp"
    Android:layout_gravity="center"
    Android:adjustViewBounds="true"
    app:imageUrl="@{segment.url}"/>

Code

  class Utils {
        companion object {
            @BindingAdapter("bind:imageUrl")
            @JvmStatic
            fun loadImage(view: ImageView, url:String) 
            {Picasso.with(view.context).load(url).error(R.drawable.error).into(view)}
    }       

L'erreur d'exécution que je reçois est la suivante:

Un BindingAdapter in in n'est pas statique et nécessite l'utilisation d'un objet, extrait du DataBindingComponent. Si vous n'utilisez pas de méthode d'inflation utilisant un DataBindingComponent, utilisez DataBindingUtil.setDefaultComponent ou rendez toutes les méthodes BindingAdapter statiques.

Des pointeurs pour le résoudre?

Cela se produit uniquement pour les attributs personnalisés. Le reste de la databindings fonctionne bien

51
Akshata

Il suffit de garder la fonction au niveau supérieur, aucun objet classe ou compagnon n’est nécessaire, cela fonctionnera puisque les fonctions de niveau supérieur dans Kotlin sont traduites en fonctions membres statiques de la classe nommée FileNameKt, sauf si remplacé par @file:JvmName annotation

@BindingAdapter("imageUrl")
fun loadImage(view: ImageView, url:String) { ... }

Une autre option consiste à annoter la fonction d'extension en tant que @BindingAdapter, cela fonctionnera puisque dans la signature en octet code, la signature correspondra exactement à la signature attendue par DataBindings (la méthode générée acceptera toujours un objet de la classe étendue comme premier argument), la fonction devrait également rester au niveau supérieur

@BindingAdapter("imageUrl")
fun ImageView.loadImage(url:String) { ... }
91
Stepango

Essayez de changer l'ordre des annotations. Il semble résoudre le problème:

class Utils {
    companion object {
        @JvmStatic @BindingAdapter("imageUrl")
        fun loadImage(view: ImageView, url:String) { ... } 
    }
} 

Le problème est que le compilateur de databindng utilise getCompanion().loadImage sinon*.
Vous pouvez le vérifier dans la classe com.your.package.databinding.*Binding Générée

* Après avoir joué un peu, j'ai remarqué que cela n'avait rien à voir avec l'ordre des annotations, mais semblait être aléatoire. Cela semble changer chaque fois que je clique sur "reconstruire". Cela pourrait être un bogue dans kapt ou dans le compilateur Kotlin

26
Lovis

Ajouter @JvmStatic Avant @BindingAdapter("imageUrl") a résolu mon problème.

Pour ex:

object BindingAdapters { @BindingAdapter("Android:visibility") @JvmStatic fun setVisibility(view: View, visible: Boolean) { view.visibility = if (visible) View.VISIBLE else View.GONE } }

Ou en utilisant l'extension:

@BindingAdapter("imageUrl")
fun ImageView.setImageUrl(url: String?) {
    Picasso.with(context).load(url).into(this)
}

Maintenant, vous pouvez utiliser cette fonction n'importe où ailleurs

2
Yazazzello

Cela a fonctionné pour moi

object ImageUtils {

        @JvmStatic @BindingAdapter("imageUrl")
        fun ImageView.loadImage(url: String?){
                GlideHelper.loadImage(url,this)
        }
}

en xml comme ceci:

imageUrl="@{file.thumbnailLink}"
1
Yogesh Paliyal

La fonction (loadImage) doit mettre en objet (Singleton en Java) pas dans la classe et définir @JvmStatic Avant @BindingAdapter("imageUrl") comme ceci:

<ImageView
Android:id="@+id/imgView”
Android:layout_width="40dp"
Android:layout_height="40dp"
Android:layout_gravity="center"
Android:adjustViewBounds="true"
imageUrl="@{segment.url}"/>

   @JvmStatic
   @BindingAdapter("bind:imageUrl")
   fun ImageView.loadImage( url:String) {
Picasso.with(this.context).load(url).error(R.drawable.error).into(this)
}
1
Fidan Bacaj