45

I am quite new in Android Data Binding. I am following this tutorial: Data Binding Library. I am trying to do an adapter that receive multiple parameters. This is my code:

XML

   <ImageView
            android:layout_width="@dimen/place_holder_size"
            android:layout_height="@dimen/place_holder_size"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_centerVertical="true"
            app:url="@{image.imageUrl}"
            app:size="@{@dimen/place_holder_size}"
            />

BINDING ADAPTER CLASS

public class ViewBindingAdapters extends BaseObservable {

@BindingAdapter({"bind:url", "bind:size"})
public static void loadImage(ImageView imageView, String url, int size) {
    if (!Strings.isNullOrEmpty(url)) {
        Picasso.with(imageView.getContext()).load(url).resize(size, size).centerCrop().into(imageView);
    }
}
....


}

But I am getting this error:

java.lang.RuntimeException: Found data binding errors. ****/ data binding error ****msg:Cannot find the setter for attribute 'app:url' with parameter type java.lang.String on android.widget.ImageView. file:... li_image_item.xml loc:30:27 - 30:40 ****\ data binding error ****

Does anybody know why??

Thanks in advance!

IrApp
  • 1,823
  • 5
  • 24
  • 42
  • what is the datatype of `image.imageUrl`? – Ravi Dec 06 '16 at 11:31
  • It is a string. – IrApp Dec 06 '16 at 11:32
  • "bind:url", "bind:size" != app:url, app:size – pskink Dec 06 '16 at 11:32
  • @pskink its ok if you write `bind:url` or `url` in `BindingAdapter`, you can access both with `app:url` – Ravi Dec 06 '16 at 11:34
  • 1
    In the tutorial they do it like this, in the paragraph: Custom Setters. – IrApp Dec 06 '16 at 11:35
  • 1
    yes indeed: `'''Custom namespaces are ignored during matching'''`, is `image.imageUrl` a String? – pskink Dec 06 '16 at 11:37
  • This method used to work like this: @BindingAdapter("imageUrl") public static void loadImage(ImageView imageView, String url) { if (!Strings.isNullOrEmpty(url)) { Picasso.with(imageView.getContext()).load(url).into(imageView); } }. But adding the new parameters is not working anymore. So the problem is not this image.imageUrl. – IrApp Dec 06 '16 at 11:41

6 Answers6

61

Problem is @dimen/place_holder_size, it returns float while you are catching it as int

change you BindingAdapter method to this

@BindingAdapter({"bind:url", "bind:size"})
public static void loadImage(ImageView imageView, String url, float size) {

}

you can refer this

Community
  • 1
  • 1
Ravi
  • 34,851
  • 21
  • 122
  • 183
  • 2
    If i set change url value then it calls this method and when i set size value then this method is called again. Is there any way that it calls only once when both values are set – Usman Rana Sep 26 '18 at 18:07
25

What I did wrong is the order of the arguments in the function. You can add multiple attributes in Binding Adapter, but they should match the arguments with the same sequence defined in the method.

Here is my code snippet for Kotlin

@BindingAdapter(value = ["bind:brand", "bind:model", "bind:age"], requireAll = false)
@JvmStatic
fun bindProductDetails(linearLayout: LinearLayout, brand: String?, model: String?, age: String?) {
    if (brand != null && !brand.isEmpty()) {
        //code
        //code

    }
}
Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
10

try this

 @BindingAdapter(value={"url", "size"}, requireAll=false)
 public static void loadImage(ImageView imageView, String url, int size) {
        if (!Strings.isNullOrEmpty(url)) {
            Picasso.with(imageView.getContext()).load(url).resize(size, size).centerCrop().into(imageView);
        }
    }
Nas
  • 2,158
  • 1
  • 21
  • 38
  • just clean and rebuild project bcoz sometime studio not update it still it not work try it with invalid catches or restart ur IDE(may be stupid bt it works sometime) – Nas Dec 06 '16 at 11:48
6

Apart from the example provided above by @Kishan Solanki, And with changes happening in the Data Binding library, all you need is to declare them with comma separated values. Example

@BindingAdapter("loadImageFrom", "widthDp")
fun loadImages(imageView: ImageView, url: String?, widthDp: Int) {
    url?.let {

        val height = (widthDp / 3) * 4
        val fullUrl = getImagePosterUrl(url)
        Picasso.get().load(fullUrl).resize(widthDp.px, height.px).into(imageView)
    }

}

Bu the most important thing to remember is that you provide the data to the adapter attributes, in the DataBinding format.

example to provide Int as parameter in XML you have to write

app:widthDp="@{120}"

which is

app:your_attribute="@{your_data}"

P. S. - Oh and one more thing, widthDp**.px** is an extension function which converts Int of a dp value to relevant pixels value based on screen density. So don't get confused.

sud007
  • 5,824
  • 4
  • 56
  • 63
5

Update

You don't need to create prefix bind:, just use this.

@BindingAdapter({"url", "size"})
public static void loadImage(ImageView imageView, String url, float size) {

}

In xml use any prefix like app:

app:url="@{image.imageUrl}"
Community
  • 1
  • 1
Khemraj Sharma
  • 57,232
  • 27
  • 203
  • 212
5

See https://developer.android.com/topic/libraries/data-binding/binding-adapters.

@BindingAdapter("imageUrl", "placeholder", requireAll = false)
fun ImageView.setImageUrl(url: String?, placeHolder: Drawable?) {
    if (url == null) {
        setImageDrawable(placeholder)
    } else {
        MyImageLoader.loadInto(this, url, placeholder)
    }
}

Note that BindingAdapter attributes and setImageUrl parameters may have different names. But they should go in the same order. If some of these attributes are defined in XML (in this example it is ImageView), this method will be called.

<ImageView 
    app:imageUrl="@{venue.imageUrl}"
    app:placeholder="@{@drawable/venueError}" />

Attributes should have the same types as defined in the method. You can also use listeners. Instead of Kotlin lambdas use interfaces.

This class should be put in the same module with XML. Otherwise you will get an error like AAPT: error: attribute imageUrl (aka com.example.imageUrl) not found..

CoolMind
  • 26,736
  • 15
  • 188
  • 224