RecyclerView和数据绑定无法正常工作

时间:2016-04-14 21:57:39

标签: android android-custom-view android-recyclerview android-databinding

这是我第一次尝试使用RecyclerView进行数据绑定,但不是我第一次使用RecyclerView本身。

由于某些原因,没有调用任何适配器方法 - 甚至没有调用getItemCount()。 这可能是我的RecyclerView的一个愚蠢问题,与数据绑定毫无关系,但我看不出有什么不妥。

       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);

适配器:

    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>

我已经检查过那里肯定有数据。 我错过了什么?

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

更新

据我所知,RecyclerView根本无法在数据绑定布局中工作。 我创建了一个单独的布局,只有我的RV,它工作得很好。 一旦我将它与我的主要布局包括在内,它就不再起作用了。

不确定这是错误还是功能。

所以,我想如果我把它变成一个自定义视图,也许它会起作用。 我的问题是我不知道如何将值传递到我的自定义视图中。

我看了here,但无法确切地知道他的意思。 这是我在自定义视图中的代码。

    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);

这会显示未找到ProfileBadgesLayoutBinding的消息。

2 个答案:

答案 0 :(得分:17)

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;
}

在项目视图中添加绑定

public class BadgeBindingHolder extends RecyclerView.ViewHolder{
    private ProfileBadgeRowBinding binding;

    public BadgeBindingHolder(View rowView, ProfileBadgeRowBinding binding) {
        super(rowView);
        this.binding = binding;
    }

    ...

}

并在bindToViewHolder设置变量

@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
}

如果您想访问视图,请在xml

的视图中添加ID
<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>

然后您可以访问bindToViewHolder

中的ID
@Override
public void bindToViewHolder(RecyclerView.ViewHolder viewHolder) {
    ProfileBadgeRowBinding binding = ((BadgeBindingHolder) viewHolder).binding;
    binding.setVariable(BR.badge, badge);
    binding.executePendingBindings();

    binding.image.setImage(...);
}

有关自定义视图的更多信息https://developer.android.com/topic/libraries/data-binding/index.html#dynamic_variables

答案 1 :(得分:0)

今天做起来要容易得多, 遵循以下示例:

public class LanguageRecyclerAdapter extends RecyclerView.Adapter<LanguageRecyclerAdapter.LanguageViewHolder> {

    private List<Language> languages;

    public class LanguageViewHolder extends RecyclerView.ViewHolder {

        final LanguageSetItemBinding item;

        public void bind(final Language language) {
            item.setLanguage(language.getName());
            item.setFlag(language.getFlagRes());
            item.getRoot().setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
//do somthing if you need
                }
            });
            item.executePendingBindings();
        }

        public LanguageViewHolder(LanguageSetItemBinding itemView) {
            super(itemView.getRoot());
            item =itemView;
        }
    }

    public LanguageRecyclerAdapter(List<Language> languages) {
        this.languages = languages;
    }

    public void onBindViewHolder(LanguageViewHolder holder, int position) {
        Language item = languages.get(position);
        holder.bind(item);
    }

    public LanguageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        LanguageSetItemBinding item = LanguageSetItemBinding.inflate(layoutInflater, parent,false);
        return new LanguageViewHolder(item);
    }

    @Override
    public int getItemCount() {
        return languages.size();
    }

    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }
}

LanguageSetItemBinding xml看起来像这样,它包含在TextViewImageView中:

<?xml version="1.0" encoding="utf-8"?>
<layout >
    <data>
        <variable name="language" type="String" />
        <variable name="flag" type="int" />
    </data>

    <android.widget.LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="166dp"
        android:layout_height="166dp"
        android:background="@color/colorWhite"
        android:orientation="vertical"
        android:layout_margin="20dp"
        android:gravity="center">
        <TextView
            android:layout_marginTop="20dp"
            android:gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="@{language}"
            android:textColor="@color/colorBlack"
            android:textAlignment="center"/>
        <ImageView
            android:textColor="?attr/errorColor"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:src="@{context.getDrawable(flag)}"
            android:gravity="center"
            android:paddingTop="3dp"/>
    </android.widget.LinearLayout>
</layout>

我有一个活动,里面有一个recyclerview,在活动OmCreateView中,我将此回收器附加到了我在上面创建的适配器上:

final ArrayList<Language> lang = new ArrayList(languageList.values());
final LanguageRecyclerAdapter adapter = new LanguageRecyclerAdapter(lang);
mBinding.languageRecyclerView.setAdapter(adapter);