I am not an expert in Android but I spent hours trying to decipher the existing solutions. The good thing is that I grasped the whole idea of data binding using BindingAdapter a bit better. For that, I am at least thankful for the existing answers (although heavily incomplete). Here a complete breakdown of the approach:
I will also use the BindingAdapter in this example. Preparing the xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="model"
            type="blahblah.SomeViewModel"/>
    </data>
    <!-- blah blah -->
    <ImageView
        android:id="@+id/ImageView"
        app:appIconDrawable="@{model.packageName}"/>
    <!-- blah blah -->
</layout>
So here I am keeping only the important stuff:
- SomeViewModelis my- ViewModelI use for data binding. You can also use a class that extends- BaseObservableand use- @Bindable. However, the- BindingAdapterin this example, doesn't have to be in a- ViewModelor- BaseObservableclass! A plain class will do! This will be illustrated later.
- app:appIconDrawable="@{model.packageName}". Yes... this was really causing me headaches! Let's break it down:- 
- app:appIconDrawable: This can be anything:- app:iCanBeAnything! Really. You can also keep- "android:src"! However, take a note on your choice, we will use it later!
- "@{model.packageName}": If you worked with data binding, this is familiar. I'll show how this is used later.
 
Let's assume we use this simple Observable class:
public class SomeViewModel extends BaseObservable {
   private String packageName; // this is what @{model.packageName}
                               // access via the getPackageName() !!!
                               // Of course this needs to be set at some
                               // point in your program, before it makes
                               // sense to use it in the BindingAdapter.
   @Bindable
   public String getPackageName() {
       return packageName;
   }
   public void setPackageName(String packageName) {
       this.packageName = packageName;
       notifyPropertyChanged(BR.packageName);
   }
   // The "appIconDrawable" is what we defined above! 
   // Remember, they have to align!! As we said, we can choose whatever "app:WHATEVER".
   // The BindingAdapter and the xml need to be aligned, that's it! :)
   //
   // The name of the function, i.e. setImageViewDrawable, can also be 
   // whatever we want! Doesn't matter.
   @BindingAdapter({"appIconDrawable"})
   public static void setImageViewDrawable(ImageView imageView, String packageName) {
       imageView.setImageDrawable(Tools.getAppIconDrawable(imageView.getContext(), packageName));
   }
}
As promised, you can also move the public static void setImageViewDrawable(), to some other class, e.g. maybe you can have a class that has a collection of BindingAdapters:
public class BindingAdapterCollection {
   @BindingAdapter({"appIconDrawable"})
   public static void setImageViewDrawable(ImageView imageView, String packageName) {
       imageView.setImageDrawable(Tools.getAppIconDrawable(imageView.getContext(), packageName));
   }
}
Another important remark is that in my Observable class I used String packageName to pass extra info to the setImageViewDrawable. You can also choose for example int resourceId, with the corresponding getters/setters, for which the adapter becomes:
public class SomeViewModel extends BaseObservable {
   private String packageName; // this is what @{model.packageName}
                               // access via the getPackageName() !!!
   private int resourceId;     // if you use this, don't forget to update
                               // your xml with: @{model.resourceId}
   @Bindable
   public String getPackageName() {
       return packageName;
   }
   public void setPackageName(String packageName) {
       this.packageName = packageName;
       notifyPropertyChanged(BR.packageName);
   }
   @Bindable
   public int getResourceId() {
       return packageName;
   }
   public void setResourceId(int resourceId) {
       this.resourceId = resourceId;
       notifyPropertyChanged(BR.resourceId);
   }
   // For this you use: app:appIconDrawable="@{model.packageName}" (passes String)
   @BindingAdapter({"appIconDrawable"})
   public static void setImageViewDrawable(ImageView imageView, String packageName) {
       imageView.setImageDrawable(Tools.getAppIconDrawable(imageView.getContext(), packageName));
   }
   // for this you use: app:appIconResourceId="@{model.resourceId}" (passes int)
   @BindingAdapter({"appIconResourceId"})
   public static void setImageViewResourceId(ImageView imageView, int resource) {
       imageView.setImageResource(resource);
   }
}