无法找到接受参数类型为 ‘androidx.lifecycle.LiveData<' 的 ~ItemBinding~ 的设置器。

huangapple go评论91阅读模式
英文:

Cannot find a setter for ~ItemBinding~ that accepts parameter type 'androidx.lifecycle.LiveData<

问题

不能找到适用于 <the_derek.dogstuff.databinding.DogItemBinding app:product> 的设置器,该设置器接受参数类型 'androidx.lifecycle.LiveData<the_derek.dogstuff.db.entity.DogEntity>'。如果绑定适配器提供了设置器,请检查适配器的注释是否正确,并且参数类型是否匹配。

我已经逐行检查了我的应用程序超过两天了。我使用了 Google 提供的“BasicSample” Android Room 应用程序来模拟我的应用程序,但是当我将它包含在我的 dog_fragment.xml 中时,出现了这个错误:

<include
  layout="@layout/dog_item"
  app:product="@{dogViewModel.dog}" />

“dog_item” 布局(dog_item.xml)用于显示狗的列表,当您点击它时,它会带您进入狗的详细信息屏幕(dog_fragment.xml)。没有它,一切都很正常,但是缺少“狗”图块以进入详细信息屏幕,只会显示一列咀嚼玩具。

dog_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
  
  <data>
    <import type="android.view.View" />
    
    <variable
      name="isLoading"
      type="boolean" />
    
    <variable
      name="dog"
      type="the_derek.dogstuff.viewmodel.DogViewModel" />
  </data>
  
  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/cardview_light_background"
    android:orientation="vertical">
    
    <include
      layout="@layout/dog_item"
      app:product="@{dogViewModel.dog}" />
    
    <FrameLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent">
      
      <TextView
        android:id="@+id/tv_loading_chew_toys"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/loading_chew_toys"
        app:visibleGone="@{isLoading}" />
      
      <FrameLayout
        android:id="@+id/chew_toys_list_wrapper"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <androidx.recyclerview.widget.RecyclerView
          android:id="@+id/chew_toy_list"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:contentDescription="@string/cd_chew_toys_list"
          app:layoutManager="LinearLayoutManager"
          app:visibleGone="@{!isLoading}" />
      </FrameLayout>
    </FrameLayout>
  </LinearLayout>
</layout>

DogFragment.java

public class DogFragment extends Fragment {

 private static final String TAG = "\t\tDogFragment";
 private static final String KEY_DOG_ID = "dog_id";

 private final ChewToyClickCallback mChewToyClickCallback =
   chewToy -> {
    // no-op
   };
 private DogFragmentBinding mBinding;
 private ChewToyAdapter mChewToyAdapter;

 public static DogFragment forDog(int dogId) {
  DogFragment fragment = new DogFragment();
  Bundle args = new Bundle();
  args.putInt(KEY_DOG_ID, dogId);
  fragment.setArguments(args);
  return fragment;
 }

 @Nullable
 @Override
 public View onCreateView(
   @NonNull LayoutInflater inflater,
   @Nullable ViewGroup container,
   @Nullable Bundle savedInstanceState) {
  mBinding = DataBindingUtil.inflate(inflater, R.layout.dog_fragment, container, false);

  mChewToyAdapter = new ChewToyAdapter(mChewToyClickCallback);
  mBinding.chewToyList.setAdapter(mChewToyAdapter);
  return mBinding.getRoot();
 }

 @Override
 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
  DogViewModel.Factory factory =
    new DogViewModel.Factory(
      requireActivity().getApplication(), requireArguments().getInt(KEY_DOG_ID));
  final DogViewModel model =
    new ViewModelProvider(this, factory).get(DogViewModel.class);

  mBinding.setLifecycleOwner(getViewLifecycleOwner());
  mBinding.setDogViewModel(model);

  subscribeToModel(model);
 }

 private void subscribeToModel(final DogViewModel model) {
  model
    .getChewToys()
    .observe(
      getViewLifecycleOwner(),
      chewToyEntities -> {
       if (chewToyEntities != null) {
        mBinding.setIsLoading(false);
        mChewToyAdapter.submitList(chewToyEntities);
       } else {
        mBinding.setIsLoading(true);
       }
      });
 }

 @Override
 public void onDestroyView() {
  mBinding = null;
  mChewToyAdapter = null;
  super.onDestroyView();
 }
}

DogViewModel.java

public class DogViewModel extends AndroidViewModel {

  private static final String TAG = "\t\tDogViewModel";
  private final LiveData<DogEntity> mObservableDog;
  private final LiveData<List<ChewToyEntity>> mObservableChewToys;

  public DogViewModel(
      @NonNull Application application, DataRepository repository, final int dogId) {
    super(application);
    mObservableChewToys = repository.loadChewToysById(dogId);
    mObservableDog = repository.loadDog(dogId);
  }

  public LiveData<List<ChewToyEntity>> getChewToys() {
    return mObservableChewToys;
  }

  public LiveData<DogEntity> getDog() {
    return mObservableDog;
  }

  public static class Factory extends ViewModelProvider.NewInstanceFactory {

    @NonNull private final Application mApplication;

    private final int mDogId;

    private final DataRepository mRepository;

    public Factory(@NonNull Application application, int dogId) {
      mApplication = application;
      mDogId = dogId;
      mRepository = ((DogApp) application).getRepository();
    }

    @SuppressWarnings("unchecked")
    @Override
    @NonNull
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
      return (T) new DogViewModel(mApplication, mRepository, mDogId);
    }
  }
}

BindingAdapters.java

public class BindingAdapters {
  @BindingAdapter("visibleGone")
  public static void showHide(View view, boolean show) {
    view.setVisibility(show ? View.VISIBLE : View.GONE);
  }
}

DogClickCallback.java

public interface DogClickCallback {
 void onClick(Dog dog);
}

dao 查询

@Query("select * from dog_table where id = :dogId")
LiveData<DogEntity> loadDog(int dogId);

DogAdapter.java

public class DogAdapter extends RecyclerView.Adapter<DogAdapter.DogViewHolder> {
 private static final String TAG = "\t\tDogAdapter";
 
 @Nullable private final DogClickCallback mDogClickCallback;
 List<? extends Dog>

<details>
<summary>英文:</summary>

&gt; Cannot find a setter for
&gt; &lt;the_derek.dogstuff.databinding.DogItemBinding app:product&gt; that
&gt; accepts parameter type
&gt; &#39;androidx.lifecycle.LiveData&lt;the_derek.dogstuff.db.entity.DogEntity&gt;&#39;
&gt; If a binding adapter provides the setter, check that the adapter is
&gt; annotated correctly and that the parameter type matches.

I’ve been going line-by-line through my app for over two days now. I used the Google provided “BasicSample” Android Room app to mock up my own app but am getting this error when I include this in my dog_fragment.xml

    &lt;include
     layout=&quot;@layout/dog_item&quot;
     app:product=&quot;@{dogViewModel.dog}&quot; /&gt;

The “dog_item” layout (dog_item.xml) is for showing a list of dogs, when you then click on it, it will bring you to a dog details screen (dog_fragment.xml). Without it, everything works great but it’s missing the “dog” tile to play into the details screen, and will only show a list of chew_toys.

&gt; dog_fragment.xml

    &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
    
    &lt;layout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
            xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;&gt;
      
      &lt;data&gt;
        &lt;import type=&quot;android.view.View&quot; /&gt;
        
        &lt;variable
          name=&quot;isLoading&quot;
          type=&quot;boolean&quot; /&gt;
        
        &lt;variable
          name=&quot;dog&quot;
          type=&quot;the_derek.dogstuff.viewmodel.DogViewModel&quot; /&gt;
      &lt;/data&gt;
      
      &lt;LinearLayout
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;
        android:background=&quot;@color/cardview_light_background&quot;
        android:orientation=&quot;vertical&quot;&gt;
        
        &lt;include
          layout=&quot;@layout/dog_item&quot;
          app:product=&quot;@{dogViewModel.dog}&quot; /&gt;
        
        &lt;FrameLayout
          android:layout_width=&quot;match_parent&quot;
          android:layout_height=&quot;match_parent&quot;&gt;
          
          &lt;TextView
            android:id=&quot;@+id/tv_loading_chew_toys&quot;
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;match_parent&quot;
            android:text=&quot;@string/loading_chew_toys&quot;
            app:visibleGone=&quot;@{isLoading}&quot; /&gt;
          
          &lt;FrameLayout
            android:id=&quot;@+id/chew_toys_list_wrapper&quot;
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;match_parent&quot;&gt;
            
            &lt;androidx.recyclerview.widget.RecyclerView
              android:id=&quot;@+id/chew_toy_list&quot;
              android:layout_width=&quot;match_parent&quot;
              android:layout_height=&quot;match_parent&quot;
              android:contentDescription=&quot;@string/cd_chew_toys_list&quot;
              app:layoutManager=&quot;LinearLayoutManager&quot;
              app:visibleGone=&quot;@{!isLoading}&quot; /&gt;
          &lt;/FrameLayout&gt;
        &lt;/FrameLayout&gt;
      &lt;/LinearLayout&gt;
    &lt;/layout&gt;

&gt; DogFragment.java

    public class DogFragment extends Fragment {
    
     private static final String TAG = &quot;\t\tDogFragment&quot;;
     private static final String KEY_DOG_ID = &quot;dog_id&quot;;
    
     private final ChewToyClickCallback mChewToyClickCallback =
       chewToy -&gt; {
        // no-op
       };
     private DogFragmentBinding mBinding;
     private ChewToyAdapter mChewToyAdapter;
    
     public static DogFragment forDog(int dogId) {
      DogFragment fragment = new DogFragment();
      Bundle args = new Bundle();
      args.putInt(KEY_DOG_ID, dogId);
      fragment.setArguments(args);
      return fragment;
     }
    
     @Nullable
     @Override
     public View onCreateView(
       @NonNull LayoutInflater inflater,
       @Nullable ViewGroup container,
       @Nullable Bundle savedInstanceState) {
      mBinding = DataBindingUtil.inflate(inflater, R.layout.dog_fragment, container, false);
     
      mChewToyAdapter = new ChewToyAdapter(mChewToyClickCallback);
      mBinding.chewToyList.setAdapter(mChewToyAdapter);
      return mBinding.getRoot();
     }
    
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
      DogViewModel.Factory factory =
        new DogViewModel.Factory(
          requireActivity().getApplication(), requireArguments().getInt(KEY_DOG_ID));
      final DogViewModel model =
        new ViewModelProvider(this, factory).get(DogViewModel.class);
    
      mBinding.setLifecycleOwner(getViewLifecycleOwner());
      mBinding.setDogViewModel(model);
    
      subscribeToModel(model);
     }
    
     private void subscribeToModel(final DogViewModel model) {
      model
        .getChewToys()
        .observe(
          getViewLifecycleOwner(),
          chewToyEntities -&gt; {
           if (chewToyEntities != null) {
            mBinding.setIsLoading(false);
            mChewToyAdapter.submitList(chewToyEntities);
           } else {
            mBinding.setIsLoading(true);
           }
          });
     }
    
     @Override
     public void onDestroyView() {
      mBinding = null;
      mChewToyAdapter = null;
      super.onDestroyView();
     }
    }

&gt; DogViewModel.java

    public class DogViewModel extends AndroidViewModel {
    
      private static final String TAG = &quot;\t\tDogViewModel&quot;;
      private final LiveData&lt;DogEntity&gt; mObservableDog;
      private final LiveData&lt;List&lt;ChewToyEntity&gt;&gt; mObservableChewToys;
    
      public DogViewModel(
          @NonNull Application application, DataRepository repository, final int dogId) {
        super(application);
        mObservableChewToys = repository.loadChewToysById(dogId);
        mObservableDog = repository.loadDog(dogId);
      }
    
      public LiveData&lt;List&lt;ChewToyEntity&gt;&gt; getChewToys() {
        return mObservableChewToys;
      }
    
      public LiveData&lt;DogEntity&gt; getDog() {
        return mObservableDog;
      }
    
      public static class Factory extends ViewModelProvider.NewInstanceFactory {
    
        @NonNull private final Application mApplication;
    
        private final int mDogId;
    
        private final DataRepository mRepository;
    
        public Factory(@NonNull Application application, int dogId) {
          mApplication = application;
          mDogId = dogId;
          mRepository = ((DogApp) application).getRepository();
        }
    
        @SuppressWarnings(&quot;unchecked&quot;)
        @Override
        @NonNull
        public &lt;T extends ViewModel&gt; T create(@NonNull Class&lt;T&gt; modelClass) {
          return (T) new DogViewModel(mApplication, mRepository, mDogId);
        }
      }
    }

&gt; BindingAdapters.java

    public class BindingAdapters {
      @BindingAdapter(&quot;visibleGone&quot;)
      public static void showHide(View view, boolean show) {
        view.setVisibility(show ? View.VISIBLE : View.GONE);
      }
    }

&gt; DogClickCallback.java

    public interface DogClickCallback {
     void onClick(Dog dog);
    }

&gt; dao query

    @Query(&quot;select * from dog_table where id = :dogId&quot;)
    LiveData&lt;DogEntity&gt; loadDog(int dogId);

&gt; DogAdapter.java

    public class DogAdapter extends RecyclerView.Adapter&lt;DogAdapter.DogViewHolder&gt; {
     private static final String TAG = &quot;\t\tDogAdapter&quot;;
    
     @Nullable private final DogClickCallback mDogClickCallback;
     List&lt;? extends Dog&gt; mDogList;
    
     public DogAdapter(@Nullable DogClickCallback clickCallback) {
       Log.i(TAG, &quot;DogAdapter: public constructor&quot;);
       mDogClickCallback = clickCallback;
       setHasStableIds(true);
     }
    
     public void setDogList(final List&lt;? extends Dog&gt; dogList) {
       if (mDogList == null) {
        mDogList = dogList;
        notifyItemRangeInserted(0, dogList.size());
       } else {
        DiffUtil.DiffResult result =
           DiffUtil.calculateDiff(
              new DiffUtil.Callback() {
                @Override
                public int getOldListSize() {
                 return mDogList.size();
                }
                @Override
                public int getNewListSize() {
                 return dogList.size();
                }
                @Override
                public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
                 return mDogList.get(oldItemPosition).getId()
                    == dogList.get(newItemPosition).getId();
                }
                @Override
                public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
                 Dog newDog = dogList.get(newItemPosition);
                 Dog oldDog = mDogList.get(oldItemPosition);
                 return newDog.getId() == oldDog.getId()
                    &amp;&amp; TextUtils.equals(newDog.getName(), oldDog.getName());
                }
              });
        mDogList = dogList;
        result.dispatchUpdatesTo(this);
       }
     }
    
     @Override
     @NonNull
     public DogViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
       DogItemBinding binding =
          DataBindingUtil.inflate(
             LayoutInflater.from(parent.getContext()), R.layout.dog_item, parent, false);
       binding.setCallback(mDogClickCallback);
       return new DogViewHolder(binding);
     }
    
     @Override
     public void onBindViewHolder(@NonNull DogViewHolder holder, int position) {
       holder.binding.setDog(mDogList.get(position));
       holder.binding.executePendingBindings();
     }
    
     @Override
     public int getItemCount() {
       return mDogList == null ? 0 : mDogList.size();
     }
    
     @Override
     public long getItemId(int position) {
       return mDogList.get(position).getId();
     }
    
     static class DogViewHolder extends RecyclerView.ViewHolder {
       final DogItemBinding binding;
       public DogViewHolder(DogItemBinding binding) {
        super(binding.getRoot());
        this.binding = binding;
       }
     }
    }


----------
----------


(DogEntity also has Dog model class, if that helps)
I&#39;ve tried Invalidate Caches/Restart, I&#39;ve tried Clean Project, Rebuild Project. I&#39;ve started a new project and copied my files into it.
Ooh, also, this is an error in addition:

    import the_derek.dogstuff.databinding.DogFragmentBindingImpl;

It tells me it cannot resolve **DogFragmentBindingImpl**
I don&#39;t know how it&#39;s not getting generated but I assume the problems are intertwined. I don&#39;t know if I missed putting any code that could help, please let me know.

(modeled after)
[android architecture-components-samples][1]


  [1]: https://github.com/android/architecture-components-samples/tree/master/BasicSample

</details>


# 答案1
**得分**: 1

这是[绑定适配器][1]错误。如果您在XML中编写了'app:product',则在您的Kotlin或Java类之一中必须有一个名为'product'的绑定适配器。例如,对于您的

&gt; app:product="@{dogViewModel.dog}"

需要有类似于以下内容的代码:

@BindingAdapter("product")
fun yourFunctionName(yourViewType: YourViewType, data: List?) {
// 在此处放置您的绑定代码
}

了解有关数据绑定和绑定适配器的更多信息。
[1]: https://developer.android.com/topic/libraries/data-binding/binding-adapters
<details>
<summary>英文:</summary>
This is [binding adapter][1] error. If you write &#39;app:product&#39; in your XML, there has to be binding adapter inside one of your kotlin or java classes with the name of &#39;product&#39;. For example, for your 
&gt; app:product=&quot;@{dogViewModel.dog}&quot;
there needs to be something like this:

@BindingAdapter("product")
fun yourFunctionName(yourViewType: YourViewType, data: List<DogEntity>?) {
// your binding code here
}

Read more about data binding and binding adapters.
[1]: https://developer.android.com/topic/libraries/data-binding/binding-adapters
</details>
# 答案2
**得分**: 1
[德里克·福西特的解决方案](https://stackoverflow.com/a/63601993) 告诉你,在 include 标签内部,参数名必须与所包含布局内使用的变量名匹配。
```xml
&lt;include
layout=&quot;@layout/dog_item&quot;
app:dog=&quot;@{dogViewModel.dog}&quot; /&gt;

dog_item

&lt;data&gt;
    
    &lt;variable
      name=&quot;dog&quot;
      type=&quot;$path.DogClass&quot; /&gt;

&lt;/data&gt;

在绑定方面,没有通用的参数名称与变量匹配,您可以自己定义名称,然后相应地进行设置。

英文:

the derek Fawcett's solution is telling you that the parameter name inside the include-tag has to match the variable name used inside the included layout.

&lt;include
layout=&quot;@layout/dog_item&quot;
app:dog=&quot;@{dogViewModel.dog}&quot; /&gt;

dog_item

&lt;data&gt;
&lt;variable
name=&quot;dog&quot;
type=&quot;$path.DogClass&quot; /&gt;
&lt;/data&gt;

There are no general parameter names to match variables when it comes to bindings, you can define the names yourself and then set them accordingly.

答案3

得分: -3

我花了几个星期或一个月的时间,认为“app:product”是一种用于XML的标准短语或约定。我以为“product”是一个类似于“gravity”或“layout”的通用术语...如果你明白我的意思的话。因为当我发表这个问题时,我对Android还不熟悉,我从来没有想过“app:”后面的术语需要根据数据中的变量进行更改。

英文:

I spent weeks or a month thinking that "app:product" was some sort of standard phrase or convention for XML. I thought "product" was a generic term used like "gravity" or "layout"..... if you get what I'm saying. Because when I posted the question I was new to Android, I never thought that the term after "app:" needed to be changed depending on the variable in data.

&lt;include
layout=&quot;@layout/dog_item&quot;
app:dog=&quot;@{dogViewModel.dog}&quot; /&gt;

答案4

得分: -4

你在这里传递了一个 LiveData 对象:

app:product="@{dogViewModel.dog}"

你需要传递:

app:product="@{dogViewModel.dog.value}"
英文:

You're passing in a LiveData object here:

app:product=&quot;@{dogViewModel.dog}&quot;

You need to pass in:

app:product=&quot;@{dogViewModel.dog.value}&quot;

huangapple
  • 本文由 发表于 2020年8月22日 02:42:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/63528445.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定