使用DataBindingComponent的Inflate方法

时间:2017-08-29 07:47:08

标签: android mvvm data-binding android-databinding

在Glide成功渲染图像后,我在更新textview时看到此错误。

  

致命异常:java.lang.IllegalStateException:必需   DataBindingComponent在类CustomBinding中为null。一个BindingAdapter   在CustomViewModel中不是静态的,需要一个对象来使用,   从DataBindingComponent中检索。如果你不使用通货膨胀   采用DataBindingComponent的方法,使用   DataBindingUtil.setDefaultComponent或生成所有BindingAdapter方法   静态的。

@BindingAdapter(value = { "android:src", "placeHolder" }, requireAll = false) 
public void setUrl(ImageView imageView, String url, Drawable placeHolder) {
          Glide.with(imageView.getContext())
              .load(url)
              .placeholder(placeHolder)
              .centerCrop()
              .listener(new Listener<String, Drawable>() {
                @Override
                public boolean onException() {
                  viewmodel.setTextVisible(true);// ERROR!
                  return false;
                }

                @Override public boolean onResourceReady() {
                  viewmodel.setTextVisible(false); // ERROR!
                  return false;
                }
              })
              .into(imageView);
        }

public void setTextVisible(boolean visibility) {
    textVisibility = visibility;
    notifyPropertyChanged(BR.textVisibility);
}

    @Bindable 
    public boolean getTextVisible() {
      return textVisibility; 
    }

这是我初始化视图模型并绑定片段内的数据的方法:

CustomBinding binding =
        DataBindingUtil.inflate(inflater, R.layout.custom, container, 
false);

    CustomViewModel viewModel = new CustomViewModel(data, context);
    binding.setHandlers(new CustomHandlers(context));
    binding.setData(viewModel);

我无法找到在viewmodel中实际实现此功能的方法。在此先感谢您的帮助。

2 个答案:

答案 0 :(得分:6)

面对相同的问题,通过在方法中添加@JvmStatic注释得到解决,并且可以正常工作。

应采用

的形式
  

@BindingAdapter(“ app:someAttribute”)

     

@JvmStatic

示例

class TestBindingHelper {

    companion object{

        @BindingAdapter("app:serviceOptions")
        @JvmStatic
        fun setServiceOptions(recyclerView: RecyclerView, listOfData: List<String>?) {
             //do something funny
        }

    }
}

答案 1 :(得分:2)

您的错误告诉您您创建的适配器不是静态的,但必须是。
我不太确定直接从绑定适配器更改视图模型是一个很好的尝试 将每个绑定适配器视为一个独立的静态方法,它位于一个单独的类(比如BindingUtills)中,它可以使用您传递给它的参数来完成工作。 在你的例子中,你不清楚如何传递URL本身(我猜不是通过android:src)。
在此示例中,适配器处理ImageView,图像URL和错误drawable:

/**
 * Loads image from url and sets it into the Image View
 * with error drawable (set into imageview if failed to load the image)
 *
 * @param imageView       {@link ImageView}
 * @param url             image url
 * @param errorDrawable   Drawable to set in case of load error.
 */
@BindingAdapter({"bind:imageUrlRound", "bind:imageError"})
public static void loadRoundImage(ImageView imageView, String url, Drawable errorDrawable) {
    Glide.with(imageView.getContext())
            .load(url)
            .asBitmap()
            .error(errorDrawable)
            .centerCrop()
            .animate(R.anim.fade_in)
            .into(new BitmapImageViewTarget(imageView) {
                @Override
                protected void setResource(Bitmap resource) {
                    RoundedBitmapDrawable circularBitmapDrawable =
                            RoundedBitmapDrawableFactory.create(imageView.getContext().getResources(), resource);
                    circularBitmapDrawable.setCircular(true);
                    imageView.setImageDrawable(circularBitmapDrawable);
                }
            });
}

布局如下:

<ImageView
...
app:imageUrlRound="@{yourViewModel.image}"
app:imageError="@{@drawable/ic_error}" />

我不确定这是一个好习惯,但您可能会尝试将视图模型添加为另一个绑定属性以及适配器的参数,并在滑行中更改它的参数回调。
附:还简化了你的视图模型(创建一个方便的映射器),只包含你想要在布局中显示的参数(即字符串整数等)恕我直言,在那里传递上下文很奇怪......