web-dev-qa-db-fra.com

Android RecyclerView.Adapter onCreateViewHolder () fonctionne

J'utilise RecyclerView.Adapter mais je suis un peu confus quant au fonctionnement de sa méthode onCreateViewHolder

  @Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    if(viewType==TYPE_ITEM) {

        View mView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.inflate_common_item, viewGroup, false);
        ViewHolder vh = new ViewHolder(mView);
        return vh;

    } else {
        View mView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.inflate_uncommon_item, viewGroup, false);
        ViewHolderFooter vh = new ViewHolderFooter(mView);
        return vh;

    }
}

Donc, si j'ai 10 éléments dans ma liste, alors pour chaque élément, cette méthode sera appelée et chaque fois qu'un nouveau ViewHolder sera créé bien sûr, il y aura une fois pour chaque affichage, mais maintenant ma question concerne l'utilisation de ListView et BaseAdapter avec nous les stockons ViewHolder dans une balise et l’utilisons. Nous ne créons pas ViewHolder pour chaque élément. 

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
            MyViewHolder mViewHolder;

            if(convertView == null) {
                    convertView = inflater.inflate(R.layout.layout_list_item, null);
                    mViewHolder = new MyViewHolder();
                    convertView.setTag(mViewHolder);
            } else {
                    mViewHolder = (MyViewHolder) convertView.getTag();
            }

            mViewHolder.tvTitle = detail(convertView, R.id.tvTitle, myList.get(position).getTitle());
            mViewHolder.tvDesc  = detail(convertView, R.id.tvDesc,  myList.get(position).getDescription());
            mViewHolder.ivIcon  = detail(convertView, R.id.ivIcon,  myList.get(position).getImgResId());

            return convertView;
    }

Nous ne créons donc pas d'objet de détenteurs de vues supplémentaire. S'il vous plaît aidez-moi à comprendre les avantages et les inconvénients.

Merci

14
Ankur Chaudhary

onCreateViewHolder crée uniquement un nouveau détenteur de vue lorsqu'il n'y a aucun détenteur de vue existant que RecyclerView puisse réutiliser. Ainsi, par exemple, si votre RecyclerView peut afficher 5 éléments à la fois, il créera 5-6 ViewHolders, puis les réutilisera automatiquement, en appelant à chaque fois onBindViewHolder

Cela ressemble à ce que votre code dans ListView fait (en vérifiant si convertView est null et si ce n'est pas le cas, en récupérant le ViewHolder existant de la balise), sauf que, avec RecyclerView, tout se fait automatiquement.

Je suppose que c’est l’un des avantages de l’utilisation de RecyclerView - vous n'avez pas à vous préoccuper autant de la réutilisation de ViewHolders que de ListView. Le problème est que RecyclerView est très personnalisable, mais n’a que très peu de fonctionnalités intégrées - contrairement à ListView qui n’est pas très personnalisable, mais possède de nombreuses fonctionnalités intégrées. 

19
Gil Moshayof

Vous pouvez utiliser ceci:

-> Créer un constructeur:

/** * Créé par Deepak Sharma le 31/10/17 . * /

public class StoreListAdapter<T> extends RecyclerView.Adapter<StoreListAdapter.ViewHolder> implements Filterable {

    private Collection<T> mItems;
    private Context context;
    private int mLayout;
    IClickable iClickable;
    private boolean isAnimationAllowed;
    private StoreSearchFilter<T> mSearchFilter;

    public StoreListAdapter(Context context)
    {
        this.context = context;
    }
    public void setData(Collection<T> items, boolean isAnimationAllowed)
    {
        mItems = items;
        this.isAnimationAllowed = isAnimationAllowed;
    }

    public void setCallback(int layout, IClickable iClickable)
    {
        this.mLayout = layout;
        this.iClickable = iClickable;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(mLayout, viewGroup, false);
        iClickable.init(view);

        StoreListAdapter.ViewHolder viewHolder = new StoreListAdapter.ViewHolder(view);    
        view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        int width = view.getMeasuredWidth();
        int height = view.getMeasuredHeight();
//        viewHolder.itemView.getLayoutParams().width = width;
        viewHolder.itemView.getLayoutParams().height = height+24;

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(StoreListAdapter.ViewHolder viewHolder, int i) {
        iClickable.execute(viewHolder, mItems.toArray()[i],viewHolder.getAdapterPosition());
        if (isAnimationAllowed)
            setAnimation(viewHolder.itemView, i);
    }

    @Override
    public int getItemCount() {
        return mItems.size()>0?mItems.size():0;
    }

    @Override
    public Filter getFilter() {
        if (mSearchFilter == null)
            mSearchFilter = new StoreSearchFilter<T>((ArrayList<StoreModel>) mItems, new IFilteredList<T>() {
                @Override
                public void onListFiltered(ArrayList<T> list) {
                    setData(list, false);
                    notifyDataSetChanged();
                }
            });
        return mSearchFilter;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        private final TextView mTextView;
        //private CheckBox mCheckBox;

        ViewHolder(View v) {
            super(v);
            mTextView = (TextView)v.findViewById(R.id.list_item);

            // Handle item click and set the selection
            /*v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // Redraw the old selection and the new
                    notifyItemChanged(selectedItem);
                    selectedItem = getLayoutPosition();
                    notifyItemChanged(selectedItem);
                }
            });*/
        }

    }

    public interface IClickable<T> {
        public void init(View view);
        public void execute(StoreListAdapter.ViewHolder holder, T object, int position);
    }

    /**
     * Here is the key method to apply the animation
     */
    private void setAnimation(View viewToAnimate, int position)
    {
            Animation animation = AnimationUtils.loadAnimation(context, Android.R.anim.slide_in_left);
            viewToAnimate.startAnimation(animation);
    }

}

-> In you Activity/Fragment:

ArrayList<StoreModel> mStoreList = new ArrayList<>();
 mStoreListAdapter = new StoreListAdapter(getActivity());
        boolean isAnimate = false;
        mStoreListAdapter.setData(mStoreList, isAnimate);

puis rappelez

mStoreListAdapter.setCallback(R.layout.store_item, new StoreListAdapter.IClickable() {
            @Override
            public void init(View view) {
                //    Toast.makeText(getActivity(), "Initialized", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void execute(StoreListAdapter.ViewHolder viewHolder, Object object, int position) {
                final StoreModel model = (StoreModel) object;

                View view = viewHolder.itemView;
                StoreListAdapter.ViewHolder holder = viewHolder;

                final CoordinatorLayout fabGameview = (CoordinatorLayout) view;
                final CardView cardView = (CardView) fabGameview.findViewById(R.id.store_item_cardview);

                TextView txtStoreName = (TextView) cardView.findViewById(R.id.txtStoreName);
                TextView txtStoreAddress = (TextView) cardView.findViewById(R.id.txtStoreAddress);
                TextView txtStoreCity = (TextView) cardView.findViewById(R.id.txtStoreCity);
                TextView txtPrizes = (TextView) cardView.findViewById(R.id.txtPrizes);
                txtStoreName.setText(model.getStoreName());
                txtStoreAddress.setText(model.getStoreAddress());
                txtStoreCity.setText(model.getStoreCity());
                txtPrizes.setText(String.valueOf(model.getPrizesAvailable()));

                LinearLayout linearDetails = (LinearLayout) cardView.findViewById(R.id.linearDetails);
                LinearLayout linearPrize = (LinearLayout) cardView.findViewById(R.id.linearPrize);

                if (clickedMarkerModel != null && clickedMarkerModel == model) {
                    holder.itemView.setSelected(true);
//                    holder.itemView.setPressed(true);
//                    linearDetails.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
//                    linearPrize.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
//                    mRecyclerStore.stopScroll();
                } else {
                    holder.itemView.setSelected(false);
//                    holder.itemView.setPressed(false);
//                    linearDetails.setBackground(ContextCompat.getDrawable(getActivity(), R.drawable.store_selector));
//                    linearPrize.setBackground(ContextCompat.getDrawable(getActivity(), R.drawable.store_selector));
                }

                // TODO Here scroll recycler view upto selected item
                /*mRecyclerStore.smoothScrollToPosition(mStoreListAdapter.getItemCount() - 1);*/

                cardView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        boolean isAddedToBackStack = true;
                        StoreDetailsAndProductListFragment storeDetailsAndProductListFragment = new StoreDetailsAndProductListFragment();
                        Bundle bundle = new Bundle();
                        bundle.putParcelable(ExtrasUtil.STORE, model);
                        storeDetailsAndProductListFragment.setArguments(bundle);
                        showOtherFragment(storeDetailsAndProductListFragment, getActivity().getFragmentManager(), isAddedToBackStack);
                    }
                });
            }
        });
        mRecyclerStore.setAdapter(mStoreListAdapter);
0
Maddy