J'essaie de définir un attribut personnalisé à l'aide de Android DataBinding Library dans mon projet Kotlin, comme suit:
<ImageView
Android:id="@+id/imgView”
Android:layout_width="40dp"
Android:layout_height="40dp"
Android:layout_gravity="center"
Android:adjustViewBounds="true"
app:imageUrl="@{segment.url}"/>
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
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) { ... }
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
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
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}"
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)
}