Android RecyclerView.Adapter onCreateViewHolder() работает
Я использую RecyclerView.Adapter, но я немного смущен относительно работы его метода 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;
}
}
Итак, у меня есть 10 элементов в моем списке, поэтому для каждого элемента этот метод будет вызван, и каждый раз, когда будет создан новый ViewHolder
, он будет один раз для каждого представления, но теперь мой вопрос, когда мы были используя ListView
и BaseAdapter
с ними, мы храним ViewHolder
в теге и используем это. Мы не создаем ViewHolder
для каждого элемента.
@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;
}
Итак, мы не создаем дополнительный объект зрителей. Пожалуйста, помогите мне понять плюсы и минусы.
Спасибо
Ответы
Ответ 1
onCreateViewHolder
создает только новый держатель вида, если нет существующих держателей вида, которые RecyclerView
может повторно использовать. Например, если ваш RecyclerView
может отображать по 5 элементов за раз, он будет создавать 5-6 ViewHolders
, а затем автоматически повторно использовать их при каждом вызове onBindViewHolder
.
Схож с тем, что делает ваш код в ListView
(проверка if convertView
на null
, а если нет, захват существующего ViewHolder
из тега), кроме, с RecyclerView
, это все сделано автоматически.
Я полагаю, что это один из плюсов с использованием RecyclerView
- вам не нужно так беспокоиться о повторном использовании ViewHolders
, как и в случае с ListView
. Кон, RecyclerView
очень настраиваемый, но имеет очень мало встроенных функций - в отличие от ListView
, который не очень настраиваемый, но имеет множество встроенных функций.
Ответ 2
Вы можете использовать это:
→ Создать конструктор:
/**
* Создано Deepak Sharma 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);
}
}
→ В вашей деятельности/фрагменте:
ArrayList<StoreModel> mStoreList = new ArrayList<>();
mStoreListAdapter = new StoreListAdapter(getActivity());
boolean isAnimate = false;
mStoreListAdapter.setData(mStoreList, isAnimate);
затем вызовите обратный вызов
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);