web-dev-qa-db-ja.com

RecyclerViewとデータバインディングが機能しない

これは、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が見つからないというメッセージが表示されます。

23
theblitz

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

21
Tom Sabel

今日の方がはるかに簡単です。次の例に従ってください:

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