RecycleView使用体验(一)

本文对比了RecycleView与ListView的区别,并详细介绍了RecycleView的使用方法、监听事件、添加项监听和数据更新策略。通过实例代码演示了如何在Android应用中灵活运用RecycleView,包括数据更新、滑动监听、点击事件处理等核心功能。

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

RecycleView替代ListView势在必行,网上有关于RecycleView介绍的博客有很多,现在我把我最近使用它的一些体会和它的一些使用用法总结如下:

一、ListView只有一个notifyDataSetChanged()一个方法,而RecycleView却有很多执行不同场景的方法

<span style="white-space:pre">	</span>public final void notifyDataSetChanged()
        public final void notifyItemChanged(int position)
        public final void notifyItemRangeChanged(int positionStart, int itemCount)
        public final void notifyItemInserted(int position) 
        public final void notifyItemMoved(int fromPosition, int toPosition)
        public final void notifyItemRangeInserted(int positionStart, int itemCount)
        public final void notifyItemRemoved(int position)
        public final void notifyItemRangeRemoved(int positionStart, int itemCount) 
现对这几个方法的使用总结如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <Button
                android:id="@+id/ItemChanged"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="1"/>
            <Button
                android:id="@+id/ItemRangeChanged"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="2"/>
            <Button
                android:id="@+id/ItemInserted"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="3"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <Button
                android:id="@+id/ItemMoved"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4"/>
            <Button
                android:id="@+id/ItemRangeInserted"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="5"/>
            <Button
                android:id="@+id/ItemRemoved"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="6"/>
            <Button
                android:id="@+id/ItemRangeRemoved"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="7"/>
        </LinearLayout>

    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_news"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fastScrollAlwaysVisible="true"
        android:fastScrollEnabled="true"
        android:scrollbarStyle="insideOverlay"
        android:scrollbars="vertical"/>


</LinearLayout>
这是MainActivity的布局文件,每个点击一个button,调用对应的方法,显示不同的结果:

MainActivity中代码如下:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements OnClickListener{
    private RecyclerView mRecyclerView;
    private List<News> mNewsList;
    private NewsAdapter mAdapter;
    private Button ItemChanged;
    private Button ItemRangeChanged;
    private Button ItemInserted;
    private Button ItemMoved;
    private Button ItemRangeInserted;
    private Button ItemRemoved;
    private Button ItemRangeRemoved;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        setupViews();
        setupEvent();
        setupData();


    }

    private void setupViews(){
        /**
         * 设置RecyclerView显示方向
         */
        mRecyclerView = (RecyclerView) findViewById(R.id.rv_news);
        LinearLayoutManager llm = new LinearLayoutManager(this);
        llm.setOrientation(LinearLayout.VERTICAL);
        mRecyclerView.setLayoutManager(llm);

        /**
         * RecyclerView增加分隔线
         */
        DividerItemDecoration divider = new DividerItemDecoration(this,LinearLayoutManager.VERTICAL,
                DensityUtil.dip2px(this,12),DensityUtil.dip2px(this,12));
        mRecyclerView.addItemDecoration(divider);

        ItemChanged = (Button) findViewById(R.id.ItemChanged);
        ItemRangeChanged = (Button) findViewById(R.id.ItemRangeChanged);
        ItemInserted = (Button) findViewById(R.id.ItemInserted);
        ItemMoved = (Button) findViewById(R.id.ItemMoved);
        ItemRangeInserted = (Button) findViewById(R.id.ItemRangeInserted);
        ItemRemoved = (Button) findViewById(R.id.ItemRemoved);
        ItemRangeRemoved = (Button) findViewById(R.id.ItemRangeRemoved);

    }

    private void setupEvent(){
        ItemChanged.setOnClickListener(this);
        ItemRangeChanged.setOnClickListener(this);
        ItemInserted.setOnClickListener(this);
        ItemMoved.setOnClickListener(this);
        ItemRangeInserted.setOnClickListener(this);
        ItemRemoved.setOnClickListener(this);
        ItemRangeRemoved.setOnClickListener(this);
    }

    private void setupData(){
        mNewsList = new ArrayList<News>();
        for (int i = 0; i < 20; i++) {
            News news = new News();
            news.news_title = "title=" + i;
            news.news_content = "content=" + i;
            mNewsList.add(news);
        }

        mAdapter = new NewsAdapter(this,mNewsList,mRecyclerView);
        mRecyclerView.setAdapter(mAdapter);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.ItemChanged :
                mNewsList.get(2).news_content = "只刷新指定的Item";
                /**
                 * 只刷新指定的Item
                 */
                mAdapter.notifyItemChanged(2);
                break;
            case R.id.ItemRangeChanged :
                mNewsList.get(3).news_content = "刷新指定范围的Item";
                mNewsList.get(4).news_content = "刷新指定范围的Item";
                mNewsList.get(5).news_content = "刷新指定范围的Item";
                /**
                 * 刷新指定范围的Item
                 * 第一个参数:从什么位置开始(下标从0开始)
                 * 第二个参数:刷新多少个Item
                 */
                mAdapter.notifyItemRangeChanged(3,3);
                break;
            case R.id.ItemInserted :
                /**
                 * 当插入的时候,需要数据有新增;
                 * 当指定插入的位置的时候,插入的数据需要在数据列表中相同的位置
                 * 例如:下面就新增了一个News对象,如果需要将其插入到第三个item,
                 * 则需要将新增的News放入mNewsList的第三个位置,然后notifyItemInserted(2)即可
                 */
                News news = new News();
                news.news_title = "title=ItemInserted";
                news.news_content = "content=ItemInserted";
                mNewsList.add(news);
                mAdapter.notifyItemInserted(mNewsList.size() - 1);
                /**
                 * 滑动到最底部
                 */
                mRecyclerView.scrollToPosition(mNewsList.size() - 1);
                break;
            case R.id.ItemMoved :
                mAdapter.notifyItemMoved(0,3);
                break;
            case R.id.ItemRangeInserted :
                /**
                 * 某个范围插入,原理和ItemInsert相同
                 * 第一个参数:从什么位置开始插入
                 * 第二个参数:插入多少条数据
                 */
                for (int i = 0; i < 3; i++) {
                    News n = new News();
                    n.news_title = "title=ItemRangeInserted" + i;
                    n.news_content = "content=ItemRangeInserted" + i;
                    mNewsList.add(n);
                }
                mAdapter.notifyItemRangeChanged(mNewsList.size() - 1, 3);
                mRecyclerView.scrollToPosition(mNewsList.size() - 1);
                break;
            case R.id.ItemRemoved :
                /**
                 * 移除第四个item
                 */
                mAdapter.notifyItemRemoved(3);
                break;
            case R.id.ItemRangeRemoved :
                /**
                 * 从第一个item开始,移除3item
                 */
                mAdapter.notifyItemRangeRemoved(0,3);
                break;
        }
    }
}


public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsViewHolder>{
    private Context mContext;
    private List<News> mNewsList;
    private RecyclerView mRecyclerView;

    public NewsAdapter(Context context, List<News> newsList, RecyclerView mRecyclerView) {
        this.mContext = context;
        this.mNewsList = newsList;
        this.mRecyclerView = mRecyclerView;
    }

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

    @Override
    public void onBindViewHolder(NewsViewHolder holder, int position) {
        holder.news_title.setText(mNewsList.get(position).news_title);
        holder.news_content.setText(mNewsList.get(position).news_content);
    }

    @Override
    public int getItemCount() {
        return mNewsList == null ? 0 : mNewsList.size();
    }

    class NewsViewHolder extends RecyclerView.ViewHolder{
        ImageView news_pic;
        TextView news_title;
        TextView news_content;
        LinearLayout news_lay;

        public NewsViewHolder(View itemView) {
            super(itemView);
            news_pic = (ImageView) itemView.findViewById(R.id.news_pic);
            news_title = (TextView) itemView.findViewById(R.id.news_title);
            news_content = (TextView) itemView.findViewById(R.id.news_content);
            news_lay = (LinearLayout) itemView.findViewById(R.id.news_lay);
        }
    }
}

代码上的解释已经很清楚了,可以仔细看下代码上的注释,就不多做详细讲解了。


二、对RecycleView的监听

通过添加OnScrollListener监听

mRecyclerView.addOnScrollListener(new OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if (newState == RecyclerView.SCROLL_STATE_IDLE) {/**滑动停止**/
            Log.d("test", "recyclerView总共的Item个数:" +
                    String.valueOf(recyclerView.getLayoutManager().getItemCount() - 1));
            Log.d("test", "recyclerView可见的Item个数:" +
                    String.valueOf(recyclerView.getChildCount()));
            /**
             * 监听是否滑动到底部
             */
            //获取可见的最后一个view
            View lastChildView = recyclerView.getChildAt(
                    recyclerView.getChildCount() - 1);


            //获取可见的最后一个view的位置
            int lastChildViewPosition = recyclerView.getChildAdapterPosition(lastChildView);

            //判断lastPosition是不是最后一个position
            if (lastChildViewPosition == recyclerView.getLayoutManager().getItemCount() - 1) {
                Toast.makeText(MainActivity.this, "滑动到底部了", Toast.LENGTH_SHORT).show();
            }

            /**监听是否滑动到顶部**/
            //获取可见的第一个view
            View firstVisibleView = recyclerView.getChildAt(0);

            //获取可见的第一个view的位置
            int firstVisiblePosition = recyclerView.getChildAdapterPosition(firstVisibleView);

            if (firstVisiblePosition == 0) {
                Toast.makeText(MainActivity.this, "滑动到顶部了", Toast.LENGTH_SHORT).show();
            }
        } else if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {/**手指还在recycleview**/
        } else if (newState == RecyclerView.SCROLL_STATE_SETTLING) {/**手指离开屏幕,单recycleview仍在滚动**/
        }
    }

    /**
     * 滑动过程中执行该函数
     * @param recyclerView
     * @param dx
     * @param dy
     */
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
    }
});
注意:

recyclerView.getChildCount()只是获取的是可见的item个数

recyclerView.getLayoutManager().getItemCount()获取的是所有的item的个数

recyclerView.getChildAt(int position) 获取某个位置的view

recyclerView.getChildAdapterPosition(View view) 获取某个view的位置


三、为RecycleView添加OnItemClickListener

我们发现,当用RecycleView来实现GridView的功能的时候,缺少点击某个Item的监听,因此可根据实际需求写个接口来监听Item的点击事件。

public class RecycleViewItemClickListener {
    private OnItemClickListener mListener;
    private static RecycleViewItemClickListener mRecycleViewItemClickListener;
    private RecycleViewItemClickListener(){}
    public static RecycleViewItemClickListener getInstance(){
        if(mRecycleViewItemClickListener == null){
            mRecycleViewItemClickListener = new RecycleViewItemClickListener();
        }
        return mRecycleViewItemClickListener;
    }

    /**监听接口**/
    public interface OnItemClickListener{
        void OnItemClick();
    }

    public void setOnItemClickListener(OnItemClickListener mItemClickListener){
        this.mListener = mItemClickListener;
    }

    public void notifyItemClickListener(){
        if(mListener != null){
            mListener.OnItemClick();
        }
    }
}
当然,还有最直接的办法,直接在创建ViewHolder类的时候实现OnClickListener接口就可以达到监听每个Item


未完待续,敬请期待第二篇。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值