Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView and Data Binding not working

Tags:

This is my first attempt at data-binding with a RecyclerView but not my first use of RecyclerView itself.

For some reason none of the adapter methods are called - not even getItemCount(). It could be a stupid problem with my RecyclerView and nothing to do with the data binding at all but I can't see anything wrong.

       View rootview = inflater.inflate(R.layout.fragment_profile_first, container, false);     // Initialize recycler view      RecyclerView badgesRV = (RecyclerView) rootview.findViewById(R.id.badgesRV);     LinearLayoutManager llm = new LinearLayoutManager(getActivity());     llm.setOrientation(LinearLayoutManager.HORIZONTAL);     badgesRV.setLayoutManager(llm);      BadgeAdapter badgeAdapter = new BadgeAdapter(profileObject.badgesEntity.badges);     badgesRV.setAdapter(badgeAdapter); 

Adapter:

    public class BadgeAdapter extends RecyclerView.Adapter<BadgeAdapter.BadgeBindingHolder>{      private static final int MAX_BADGES_TO_DISPLAY = 5;     private BadgeObject[] badges;      public BadgeAdapter(BadgeObject[] badges){         this.badges = badges;     }      @Override     public BadgeBindingHolder onCreateViewHolder(ViewGroup parent, int viewType) {         View v = LayoutInflater.from(parent.getContext())                 .inflate(R.layout.profile_badge_row, parent, false);         BadgeBindingHolder holder = new BadgeBindingHolder(v);         return holder;     }      @Override     public void onBindViewHolder(BadgeBindingHolder holder, int position) {         final BadgeObject badgeObject = badges[position];         holder.getBinding().setVariable(BR.badge, badgeObject);         holder.getBinding().executePendingBindings();      }      @Override     public int getItemCount() {         Log.d(TAG, "item count = " + Math.min(MAX_BADGES_TO_DISPLAY, badges.length));         return Math.min(MAX_BADGES_TO_DISPLAY, badges.length);     }      public class BadgeBindingHolder extends RecyclerView.ViewHolder{         private ViewDataBinding binding;          public BadgeBindingHolder(View rowView) {             super(rowView);             binding = DataBindingUtil.bind(rowView);         }         public ViewDataBinding getBinding() {             return binding;         }     } } 

profile_badge_row.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">  <data>     <variable name="badge" type="parseJsonEntities.requestObjects.BadgeObject"/> </data>  <LinearLayout     android:orientation="vertical" android:layout_width="match_parent"     android:layout_height="match_parent">      <ImageView         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:src="@{badge.badgeImage}"/>  </LinearLayout> 

I have checked and there is definitely data there. What have I missed?

=====================

Update:

From what I can tell RecyclerView simply doesn't work inside a Data Binding layout. I created a separate layout with just my RV and it worked perfectly. As soon as I included it with my main layout it ceased to work.

Not sure if this is a bug or a feature.

So, I thought that maybe if I make it a custom view maybe it will work and it does. My problem is I don't know how to pass a value into my custom view.

I looked here but couldn't figure out exactly what he means. This is my code in the custom view.

    LayoutInflater inflater = (LayoutInflater)             context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);     View view = inflater.inflate(R.layout.profile_badges_layout, this, true);     ProfileBadgesLayoutBinding binding = ProfileBadgesLayoutBinding.inflate(inflater);      RecyclerView badgesRV = (RecyclerView) view.findViewById(R.id.badgesRV);      LinearLayoutManager llm = new LinearLayoutManager(context);     llm.setOrientation(LinearLayoutManager.HORIZONTAL);     badgesRV.setLayoutManager(llm);      BadgeAdapter badgeAdapter = new BadgeAdapter(null);     badgesRV.setAdapter(badgeAdapter); 

This gives a message that ProfileBadgesLayoutBinding is not found.

like image 569
theblitz Avatar asked Apr 14 '16 21:04

theblitz


1 Answers

In your onCreateViewHolder:

@Override public BadgeBindingHolder onCreateViewHolder(ViewGroup parent, int viewType) {     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);     ProfileBadgeRowBinding binding = DataBindingUtil.inflate(inflater, R.layout.profile_badge_row, parent, false);     BadgeBindingHolder holder = new BadgeBindingHolder(binding.getRoot(), binding);     return holder; } 

And add the binding in your Item View

public class BadgeBindingHolder extends RecyclerView.ViewHolder{     private ProfileBadgeRowBinding binding;      public BadgeBindingHolder(View rowView, ProfileBadgeRowBinding binding) {         super(rowView);         this.binding = binding;     }      ...  } 

And in the bindToViewHolder set the variable

@Override public void bindToViewHolder(RecyclerView.ViewHolder viewHolder) {     ProfileBadgeRowBinding binding = ((BadgeBindingHolder) viewHolder).binding;     binding.setVariable(BR.badge, badge);     binding.executePendingBindings(); // This line is important, it will force to load the variable in a custom view } 

If you want to access a view, add an id to a view in your xml.

<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">      <data>         <variable name="badge" type="parseJsonEntities.requestObjects.BadgeObject"/>     </data>      <LinearLayout         android:orientation="vertical" android:layout_width="match_parent"         android:layout_height="match_parent">          <ImageView             android:id="@+id/image"             android:layout_width="wrap_content"             android:layout_height="wrap_content" />      </LinearLayout> </layout> 

And then you can access the id's in your bindToViewHolder

@Override public void bindToViewHolder(RecyclerView.ViewHolder viewHolder) {     ProfileBadgeRowBinding binding = ((BadgeBindingHolder) viewHolder).binding;     binding.setVariable(BR.badge, badge);     binding.executePendingBindings();      binding.image.setImage(...); } 

More about custom views https://developer.android.com/topic/libraries/data-binding/index.html#dynamic_variables

like image 85
Tom Sabel Avatar answered Sep 20 '22 13:09

Tom Sabel