Android——RecyclerView入门学习之RecyclerView.Adapter

本文详细介绍了RecyclerView的高级使用技巧,包括自定义Adapter、ViewHolder的优化、点击事件处理、数据更新策略及HeaderView与FooterView的优雅集成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习资料:

之前使用RecyclerView.Adapter,基本就类似套用公式,死步骤,对Adapter感到既熟悉又陌生。从去年我开始接触学习Android之时,RecyclerView已经开始大量被运用,逐步取代ListView。遂,正好,那就先直接学习RecyclerView.Adapter相关知识


1. RecyclerView.Adapter适配器

RecyclerView.Adapter,一个抽象类,并支持泛型

public static abstract class Adapter<VH extends ViewHolder> {
   ...
}

定义一个MyRecyclerViewAdapter继承RecyclerView.Adapter后,Android Stuido提醒需要重写3个方法,在重写3个方法前,一般会先定义一个Holder继承RecycelrView.ViewHolder,之后直接在MyRecyclerViewAdapter上,指定泛型就是RecyclerHolder

3个需要必须重写的方法:

方法1public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)

方法2:public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)

方法3:public int getItemCount()

在指定了泛型为RecyclerHoler后,方法2也会根据泛型改变onBindViewHolder(RecyclerHolder holder, int position)


1.1 onCreateViewHolder(ViewGroup parent, int viewType)创建Holder

源码:

/**
 * Called when RecyclerView needs a new {@link ViewHolder} of the given type to represent an item.
 * 
 * @param parent The ViewGroup into which the new View will be added after it is bound to an adapter position.
 * @param viewType The view type of the new View.
 *
 * @return A new ViewHolder that holds a View of the given view type.
 */
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
  • ViewGroup parent:可以简单理解为item的根ViewGroupitem的子控件加载在其中
  • int viewTypeitem的类型,可以根据viewType来创建不同的ViewHolder,来加载不同的类型的item

这个方法就是用来创建出一个新的ViewHolder,可以根据需求的itemType,创建出多个ViewHolder。创建多个itemType时,需要getItemViewType(int position)方法配合


1.2 onBindViewHolder(RecyclerHolder holder, int position)绑定ViewHolder

源码:

**
*Called by RecyclerView to display the data at the specified position.
*This method should update the contents of the {@link ViewHolder#itemView} to reflect the item at the given position.
* 
*@param holder The ViewHolder which should be updated to represent the contents of the item at the given position in the data set.
*@param position The position of the item within the adapter's data set.
*/

public abstract void onBindViewHolder(VH holder, int position);
  • VH holder:就是在onCreateViewHolder()方法中,创建的ViewHolder
  • int positionitem对应的DataList数据源集合的postion

postion就是adapter positionRecycelrViewitem的数量,就是根据DataList数据源集合的数量来创建的


1.3 getItemCount()获取Item的数目

源码:

/**
 * Returns the total number of items in the data set held by the adapter.
 *
 * @return The total number of items in this adapter.
 */
public abstract int getItemCount();

这个方法的返回值,便是RecyclerView中实际item的数量。有些情况下,当增加了HeaderView或者FooterView后,需要注意考虑这个返回值


1.4 简单实用

一个最简单的RecyclerViewAdapter

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.RecyclerHolder> {
    private Context mContext;
    private List<String> dataList = new ArrayList<>();

    public MyRecyclerViewAdapter(RecyclerView recyclerView) {
        this.mContext = recyclerView.getContext();
    }

    public void setData(List<String> dataList) {
        if (null != dataList) {
            this.dataList.clear();
            this.dataList.addAll(dataList);
            notifyDataSetChanged();
        }
    }

    @Override
    public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout, parent, false);
        return new RecyclerHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerHolder holder, int position) {
        holder.textView.setText(dataList.get(position));
    }

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

    class RecyclerHolder extends RecyclerView.ViewHolder {
        TextView textView;

        private RecyclerHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv__id_item_layout);
        }
    }
}

我的个人习惯是单独使用一个setData()方法将DataList传递进Adapter,看到网上有一些博客中会通过构造方法传递。我一般会在网络请求前就初始化Adapter,当异步网络请求拿到解析过的JSON数据后,调用这个方法将数据加载进Adapter,即使做了分页,也可以比较方。但感觉这种方法终究会浪费一点性能

注意,在 onCreateViewHolder()方法中:

View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout, parent, false);

inflate()方法使用的是3个参数的方法。


1.4.1 问题

以前使用2个参数的方法inflate(@LayoutRes int resource, @Nullable ViewGroup root),下面的形式

View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout,null);

遇到的一个问题


2个参数方法遇到的问题

两种方法,使用的是同一套布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv__id_item_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:textAllCaps="false"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

</LinearLayout>

item内的TextView的宽是match_parent,但使用两个参数的方法时,看起来却是wrap_content的效果


1.4.2尝试从源码中找问题

两个参数的方法源码

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
        return inflate(resource, root, root != null);
}

两个参数的方法内部调用了3个参数的方法,此时inflate(resourceId, null, false)rootnullattachToRootfalse

最终来到了这里,只保留了部分代码:

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    ...

    View result = root;

    ...

    // Temp is the root view that was found in the xml
    final View temp = createViewFromTag(root, name, inflaterContext, attrs);

    ViewGroup.LayoutParams params = null;
    ...

    if (root != null) {

        ...

        params = root.generateLayoutParams(attrs);

        ...               
    }

    ...

    rInflateChildren(parser, temp, attrs, true);

    ...

    if (root == null || !attachToRoot) {
        result = temp;
    }
 }

使用两个参数的inflate()方法,ViewGroup.LayoutParams params最终为null;而如果使用3个参数的方法,最终params = params = root.generateLayoutParams(attrs)

这里为了减少出现问题的出现,就使用3个参数的方法inflate(R.layout.id_rv_item_layout, parent, false)

这里看源码也就看了这小段一段,inflate()方法的完整过程还是比较复杂的,比较浅显的知道问题出在哪里后,没有深挖


1.4 点击事件

完整代码:

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.RecyclerHolder> {
    private Context mContext;
    private List<String> dataList = new ArrayList<>();
    private onRecyclerItemClickerListener mListener;

    public MyRecyclerViewAdapter(RecyclerView recyclerView) {
        this.mContext = recyclerView.getContext();
    }


    /**
     * 增加点击监听
     */
    public void setItemListener(onRecyclerItemClickerListener mListener) {
        this.mListener = mListener;
    }

    /**
     * 设置数据源
     */
    public void setData(List<String> dataList) {
        if (null != dataList) {
            this.dataList.clear();
            this.dataList.addAll(dataList);
            notifyDataSetChanged();
        }
    }

    public List<String> getDataList() {
        return dataList;
    }

    @Override
    public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout, parent, false);
        // View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout,null);
        return new RecyclerHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerHolder holder, int position) {
        holder.textView.setText(dataList.get(position));
        holder.textView.setOnClickListener(getOnClickListener(position));
    }

    private View.OnClickListener getOnClickListener(final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != mListener && null != v) {
                    mListener.onRecyclerItemClick(v, dataList.get(position), position);
                }
            }
        };
    }


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

    class RecyclerHolder extends RecyclerView.ViewHolder {
        TextView textView;

        private RecyclerHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv__id_item_layout);
        }
    }

    /**
     * 点击监听回调接口
     */
    public interface onRecyclerItemClickerListener {
        void onRecyclerItemClick(View view, Object data, int position);
    }
}

定义一个接口onRecyclerItemClickerListener,这样可以在Actiivty设置监听对象,之后为TextView设置点击监听事件,在TextView的点击事件方法中,使用onRecyclerItemClick()进行回调


在Activity中使用:

//设置点击事件
adapter.setItemListener(new MyRecyclerViewAdapter.onRecyclerItemClickerListener() {
    @Override
    public void onRecyclerItemClick(View view, Object data, int position) {
        String s = (String) data;
        adapter.getDataList().set(position, s + "---->hi");
            adapter.notifyItemChanged(position);
        }
});

在监控对象回调方法中,使用了notifyItemChanged(position)来进行局部刷新


点击进行局部刷新

但这种方式会new出一大堆View.OnClickListener,还有一种思路是利用RecycelrViewonTouchListenerGestureDetector手势来进行设置,可以看看三种方式实现RecyclerView的Item点击事件


1.5 一系列的notifyData方法

一共有10个方法

方法作用
notifyDataSetChanged()通知RecycelrView进行全局刷新
notifyItemChanged(int position)通知RecycelrViewadapter position处局进行部刷新
notifyItemRemoved(int position)通知RecyclerView移除在adapter position处的item
notifyItemMoved(int fromPosition, int toPosition)通知RecyclerView移除从fromPositiontoPositionitem
notifyItemRangeRemoved(int positionStart, int itemCount)通知RecyclerView移除从positionStart开始的itemCountitem
notifyItemChanged(int position, Object payload)通知RecyclerView改变指定positionitemobject
notifyItemRangeChanged(int positionStart,int itemCount)通知RecyclerViewpositionStart开始改变itemCountitem
notifyItemRangeChanged(int positionStart,int itemCount,Object payload)通知RecyclerViewpositionStart开始改变itemCountitem的对象
notifyItemInserted(int position)通知RecyclerViewposition处插入一个item
notifyItemRangeInserted(int positionStart, int itemCount)通知RecyclerViewpositionStart开始插入itemCountitem

有些情况下,方法需要考虑组合使用,否则可能出现position错乱,例如

在Adapter中移除或者插入item

/**
 * 移除指定Position的Item
 */
public void remove(int position) {
    if (dataList.size() == 0) return;
    dataList.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, dataList.size() - position);
}

//在Activity中使用 ,设置点击事件
adapter.setItemListener(new MyRecyclerViewAdapter.onRecyclerItemClickerListener() {
    @Override
    public void onRecyclerItemClick(View view, Object data, int position) {
        adapter.remove(position);
        // String s = (String) data;
        // adapter.inserted(position,s+"---->hi");
    }
});

//在指定位置插入一个item
public void inserted(int position, String s) {
    if (dataList.size() == 0) return;
    dataList.add(position, s);
    notifyItemInserted(position);
    notifyItemRangeChanged(position, dataList.size() - position);
}

notifyItemRemoved(position)虽然通知移除了RecycelrViewposition位置上的itemA,但itemA之后的一系列item也需要进行改变,也需要通知RecyclerView进行改变

但这两个方法性能上都有问题,卡顿比较明显,应该会有更好的动态改变或者动态插入item的方法,以后学到了再补充


1.5 简易的封装

通用的ViewHolder:

public class BaseViewHolder extends RecyclerView.ViewHolder {
    private final SparseArray<View> sparseArray;

    public BaseViewHolder(View itemView) {
        super(itemView);
        this.sparseArray = new SparseArray<>(8); //一般一个Item 不会超过8种控件
    }

    public <T extends View> T getView(int viewId) {
        View view = sparseArray.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            sparseArray.put(viewId, view);
        }
        return (T) view;
    }

    public BaseViewHolder setText(int viewId, String text) {
        TextView tv = getView(viewId);
        if (tv != null) {
            tv.setText(text);
        }
        return this;
    }
}

主要思路就是使用SparseArray<View>将控件存起来


适配器:

public abstract class CommonBaseAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
    protected List<T> data = new ArrayList<>();
    protected int itemLayoutId;
    protected Context mContext;
    private onRecyclerItemClickerListener mListener;

    public CommonBaseAdapter(RecyclerView rv, @LayoutRes int itemLayoutId) {
        this.itemLayoutId = itemLayoutId;
        this.mContext = rv.getContext();
    }

    public void setData(List<T> data) {
        if (data != null) {
            this.data.clear();
            this.data.addAll(data);
            notifyDataSetChanged();
        }
    }

    /**
     *  增加点击监听
     */
    public void setItemListener(onRecyclerItemClickerListener mListener) {
        this.mListener = mListener;
    }

    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //这里使用3个参数的方法
        View view = LayoutInflater.from(mContext).inflate(itemLayoutId, parent, false);
        return new BaseViewHolder(view);
    }

    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        bindViewData(holder, data.get(position), position);
        holder.itemView.setOnClickListener(getOnClickListener(position));
    }

    private View.OnClickListener getOnClickListener(final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mListener != null && v != null) {
                    mListener.onRecyclerItemClick(v, data.get(position), position);
                }
            }
        };
    }

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

    public abstract void bindViewData(BaseViewHolder holder, T item, int position);

    interface onRecyclerItemClickerListener {
        void onRecyclerItemClick(View view, Object data, int position);
    }
}

内部提供一个抽象方法bindViewData(),子类重写抽象方法来做一些具体的操作。

封装的很简单,但平常学习使用也能减少一些重复代码。网上有很多强大的封装,可以再深入学习一下为RecyclerView打造通用Adapter让RecyclerView更加好用


使用:

public class RecyclerViewAdapter extends CommonBaseAdapter<String> {

    public RecyclerViewAdapter(RecyclerView rv, @LayoutRes int itemLayoutId, @IdRes int resId) {
        super(rv, itemLayoutId);

    }

    @Override
    public void bindViewData(BaseViewHolder holder, String item, int position) {
        holder.setText(R.id.textViewId, item);
    }
}

Activity中就可以进行使用

这个简易的封装并没有对添加加载图片的方法。加载图片的方法一开始也我封装在了这个CommonBaseAdapter中,但后来发现直接封装在这里并不是好的思路

图片需要做的处理比较多,而且主流的库有3个,为了易于维护,还是将图片的操作单独再封装在一个工具类中,在CommonBaseAdapter中使用操作图片的工具类比较好


1.6 添加HeaderView和FooterViewiew

学的鸿洋大神的代码和思路,涉及到了装饰模式。还有一种添加方式是直接通过使用多种item直接在现有的CommonBaseAdapter来修改,但感觉这种思路需要对CommonBaseAdapter改动的代码太多,点击事件的position也需要考虑,不如鸿洋大神的这种思路易于开发和维护

代码:

public class HeaderAndFooterAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    private CommonBaseAdapter mAdapter;

    private static final int HEADER_VIEW_TYPE = 2 << 6;
    private static final int FOOTER_VIEW_TYPE = 2 << 5;

    private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();
    private SparseArrayCompat<View> mFooterViews = new SparseArrayCompat<>();

    public HeaderAndFooterAdapter(CommonBaseAdapter mAdapter) {
        this.mAdapter = mAdapter;
    }

    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (null != mHeaderViews.get(viewType)) {
            return new HeaderAndFooterHolder(mHeaderViews.get(viewType));
        } else if (null != mFooterViews.get(viewType)) {
            return new HeaderAndFooterHolder(mFooterViews.get(viewType));
        }
        return mAdapter.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        if (isHeaderViewPosition(position)) return;
        if (isFooterViewPosition(position)) return;
        mAdapter.onBindViewHolder(holder, position - getHeaderViewCount());
    }

    @Override
    public int getItemViewType(int position) {
        if (isHeaderViewPosition(position)) {
            return mHeaderViews.keyAt(position);
        } else if (isFooterViewPosition(position)) {
            return mFooterViews.keyAt(position-getHeaderViewCount()-getAdapterItemCount());
        }
        return mAdapter.getItemViewType(position - getHeaderViewCount());
    }

    @Override
    public int getItemCount() {
        return getHeaderViewCount() + getFooterViewCount() + getAdapterItemCount();
    }

    /**
     * 加入HeaderView
     */
    public void addHeaderView(View view) {
        mHeaderViews.put(mHeaderViews.size() + HEADER_VIEW_TYPE, view);
    }

    /**
     * 加入FooterView
     */
    public void addFootView(View view) {
        mFooterViews.put(mFooterViews.size() + FOOTER_VIEW_TYPE, view);
    }

    /**
     * HeaderView 的数目
     */
    public int getHeaderViewCount() {
        return mHeaderViews.size();
    }

    /**
     * FooterView 的数目
     */
    public int getFooterViewCount() {
        return mFooterViews.size();
    }

    /**
     * 是不是HeaderView的Position
     */
    private boolean isHeaderViewPosition(int position) {
        return position < getHeaderViewCount();
    }


    /**
     * 是不是FooterView的Position
     */
    private boolean isFooterViewPosition(int position) {
        return position >= getHeaderViewCount() + getAdapterItemCount();
    }

    /**
     * 得到Adapter中Item的数目
     */
    private int getAdapterItemCount() {
        return mAdapter.getItemCount();
    }

    private class HeaderAndFooterHolder extends BaseViewHolder {
        private HeaderAndFooterHolder(View itemView) {
            super(itemView);
        }
    }
}

封装的思路:
add进来的view进行保存,当加载item时,利用itemTypeview进行类型判断,如果是HeaderView或者FooterView就创建HeaderAndFooterHolder,然后绑定只是用来显示并没有对HeaderView或者FooterView做其他更多事件的处理


使用也比较方便:

//数据适配器
RecyclerViewAdapter adapter = new RecyclerViewAdapter(rv, R.layout.id_rv_item_layout, R.id.tv__id_item_layout);
//头View适配器
HeaderAndFooterAdapter headerAndFooterAdapter = new HeaderAndFooterAdapter(adapter);
//HeaderView
TextView headerView = new TextView(this);
headerView.setBackgroundColor(Color.BLACK);
headerView.setTextColor(Color.WHITE);
headerView.setWidth(1080);
headerView.setTextSize(50);
headerView.setText("我是头");
headerAndFooterAdapter.addHeaderView(headerView);
//设置适配器
rv.setAdapter(headerAndFooterAdapter);
//添加数据
addData(adapter);

添加HeaderView

RecyelrView设置的适配器是headerAndFooterAdapter,而添加数据使用的是adapterHeaderAndFooterAdapter是支持添加多个HeaderView


1.6.1 GridLayoutManger和StaggeredGridLayoutManager跨列问题

上面添加HeaderView时,使用的LinerLayoutManager,当使用GridLayoutManger时,便会有问题

HeaderView不能单独占据一行


GridLayoutManager遇到问题

加入针对GridLayoutManager跨列处理的代码:

/**
 *当RecyelrView开始观察Adapter会被回调
 */
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    mAdapter.onAttachedToRecyclerView(recyclerView);
    final RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
    if (manager instanceof GridLayoutManager) {
        final GridLayoutManager gridLayoutManager = (GridLayoutManager) manager;
        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                int viewType = getItemViewType(position);
                //如果是HeaderView或者是FooterView,设置占据gridLayoutManager.getSpanCount()列
                if (null != mHeaderViews.get(viewType) || null != mFooterViews.get(viewType)) {
                    return gridLayoutManager.getSpanCount();
                }
                return 1;
            }
        });
    }
}

跨列处理


当布局管理器为GridLayouManger时,对当前要的添加的item进行判断,如果是HeaderView或者是FooterView,就进行跨列处理,单独占据一行


加入针对StaggeredGridLayoutManager跨列处理的代码:

/**
 * 一个item通过adapter开始显示会被回调
 */
@Override
public void onViewAttachedToWindow(BaseViewHolder holder) {
    super.onViewAttachedToWindow(holder);
    int position = holder.getLayoutPosition();
    if (isHeaderViewPosition(position)||isFooterViewPosition(position)){
        ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
        if (null != lp && lp instanceof StaggeredGridLayoutManager.LayoutParams){
            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
            p.setFullSpan(true);//占满一行
        }
    }
}

瀑布流跨列


当布局管理器为StaggeredGridLayoutManager时,对当前要的添加的item进行判断,如果是HeaderView或者是FooterView,就设置setFullSpan(true),占满一行

### 回答1: RecyclerView是一个Android的UI组件,用于在列表或网格中显示大量数据。它可以自动回收不可见的视图,提高性能,并且支持多种布局管理器,如线性布局、网格布局和瀑布流布局等。开发者可以通过适配器来提供数据,并且可以自定义视图的外观和交互。 ### 回答2: RecyclerViewAndroid平台上的一个强大的视图容器,用于展示大量数据的列表或网格布局。它是Android支持库中的一个组件,提供了比ListView更灵活和高效的方式来展示和处理数据。 相比于ListView,RecyclerView具有更好的性能和扩展性。它采用了ViewHolder模式和布局管理器的设计思想,使得列表中的每个列表项都可以重用,并且只加载可见区域的列表项,从而减少了内存消耗和渲染时间。通过适配器(Adapter)和数据集(Dataset)的结合,RecyclerView可以很方便地处理数据的变化和更新,实现了数据的分离和重用。 RecyclerView的布局管理器(Layout Manager)提供了多种布局方式,如线性布局、网格布局、瀑布流布局等,开发者可以根据需求选择合适的布局方式来展示数据。此外,RecyclerView还支持添加分割线、动画效果等,使得列表项具有更加丰富和炫酷的展示效果。 除了基本的数据展示功能,RecyclerView还提供了交互事件的处理接口,如点击、长按、滑动、拖拽等,这使得开发者可以方便地处理用户的交互操作,并实现一些复杂的列表交互效果。 总之,RecyclerViewAndroid开发中常用的一个组件,它通过适配器、布局管理器和数据集的组合,提供了高效、灵活和可扩展的数据展示和交互功能,可以满足各种复杂列表布局和需求。 ### 回答3: RecyclerView是一个在安卓开发中常用的控件,用于展示大量数据。它是ListView的升级版本,相比ListView,RecyclerView可以更灵活地管理和展示数据。 首先,RecyclerView使用了ViewHolder模式来优化视图的复用,减少了内存的占用和视图的创建。通过ViewHolder模式,可以减少findViewById方法的调用次数,提高了列表的滑动性能。 其次,RecyclerView通过LayoutManager来管理视图的布局方式。它提供了多种布局方式,如线性布局、网格布局、瀑布流布局等,开发者可以根据需求自由选择。布局方式的灵活性使开发者可以更好地适应不同的展示效果。 另外,RecyclerView支持动画效果的添加和删除。通过添加ItemAnimator,可以在数据增加或删除时给列表添加动画效果,使用户体验更加丰富。 除此之外,RecyclerView还提供了各种辅助类和接口,如ItemDecoration、ItemTouchHelper等,可以方便地添加分割线、滑动删除等功能。 总的来说,RecyclerView是一种非常强大的控件,适用于展示大量数据的场景。它通过ViewHolder模式、LayoutManager和动画效果等特性,提高了列表的性能和用户体验,为开发者在安卓应用的开发中带来了便利。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值