安卓recycleview

本文详细介绍如何在Android开发中使用RecyclerView,包括依赖添加、主类配置、自定义Adapter与ViewHolder实现,以及数据绑定和事件处理。通过实例演示,展示了如何创建适配器和视图持有者,以及如何在列表项中展示数据。

添加依赖

implementation 'com.android.support:recyclerview-v7:+'

list.java (主类)

        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        final List<Book> data = new ArrayList<>();
        for(int i = 0; i < 20; i++) {
            Book b = new Book("book"+i,"100");
            data.add(b);
        }

        final MyRecyclerViewAdapter myAdapter = new MyRecyclerViewAdapter<Book>(this, R.layout.item, data) {
            @Override
            public void convert(MyViewHolder holder, Book s) {
                // Colloction是自定义的一个类,封装了数据信息,也可以直接将数据做成一个Map,那么这里就是Map<String, Object>
                TextView name = holder.getView(R.id.name);
                name.setText(s.getBookName());
                TextView price = holder.getView(R.id.price);
                price.setText(s.getBookPrice());
            }
        };

        recyclerView.setAdapter(myAdapter);   

 自定义Adapter

public abstract class MyRecyclerViewAdapter<T> extends RecyclerView.Adapter<MyViewHolder> {
    private List<T> data;
    private Context context;
    private int layout;
    public abstract void convert(MyViewHolder holder, T t);

    public MyRecyclerViewAdapter(Context _context, int _layoutId, List _data) {
        data = _data;
        context = _context;
        layout = _layoutId;
    }

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

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        MyViewHolder holder = MyViewHolder.get(context, parent, layout);
        return holder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        convert(holder, data.get(position)); // convert函数需要重写
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                data.remove(position);
                notifyDataSetChanged();
//                notifyItemRemoved(position);
//                notifyItemRangeChanged(position, getItemCount());
                Toast.makeText(context, "删除"+position, Toast.LENGTH_SHORT).show();
            }
        });
//        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
//            @Override
//            public boolean onLongClick(View view) {
//                data.remove(position);
//                notifyDataSetChanged();
//                Toast.makeText(context, "删除"+position, Toast.LENGTH_SHORT).show();
//                return false;  // true 表示已经完整地处理了事件,不希望其他回调方法再处理
//            }
//        });
    }
}

自定义ViewHolder

public class MyViewHolder extends RecyclerView.ViewHolder{
    private SparseArray<View> views;
    private View view;

    public MyViewHolder(Context _context, View _view, ViewGroup _viewGroup){
        super(_view);
        view = _view;
        views = new SparseArray<View>();
    }

    public static MyViewHolder get(Context _context, ViewGroup _viewGroup, int _layoutId) {
        View _view = LayoutInflater.from(_context).inflate(_layoutId, _viewGroup, false);
        MyViewHolder holder = new MyViewHolder(_context, _view, _viewGroup);
        return holder;
    }

    public <T extends View> T getView(int _viewId) {
        View _view = views.get(_viewId);
        if (_view == null) {
            // 创建view
            _view = view.findViewById(_viewId);
            // 将view存入views
            views.put(_viewId, _view);
        }
        return (T)_view;
    }
}

主xml

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

列表项xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_marginTop="4dp"
    android:background="@android:color/white"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/name"
        android:layout_width="100dp"
        android:layout_height="match_parent"/>
    <TextView
        android:id="@+id/price"
        android:layout_width="100dp"
        android:layout_height="match_parent"/>
</LinearLayout>

数据的类

public class Book {
    private String bookName;
    private String bookPrice;
    public Book(String bookName, String bookPrice) {
        this.bookName = bookName;
        this.bookPrice = bookPrice;
    }
    public String getBookName() {
        return bookName;
    }

    public String getBookPrice() {
        return bookPrice;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public void setBookPrice(String bookPrice) {
        this.bookPrice = bookPrice;
    }
}

 

在 Android 开发中,`RecyclerView` 是一个非常强大的 UI 组件,用于展示大量数据并实现高效的滚动和渲染性能。它通过灵活的布局管理器(LayoutManager)、适配器(Adapter)和视图持有者(ViewHolder)模式,支持多种复杂的列表和网格布局。 ### 布局管理器的使用 `RecyclerView` 支持多种布局管理器,其中最常用的是 `LinearLayoutManager`、`GridLayoutManager` 和 `StaggeredGridLayoutManager`。对于需要多列或多行布局的情况,`GridLayoutManager` 提供了灵活的配置方式。例如,在某些场景下需要让不同的条目占据不同的行列数,可以通过重写 `SpanSizeLookup` 实现: ```java @Override public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int itemViewType = getItemViewType(position); if (itemViewType == LEFT) { return 2; } else if (itemViewType == CENTER) { return 6; } else if (itemViewType == RIGHT) { return 3; } return 6; } }); } } ``` 这种方式特别适用于需要在同一 `RecyclerView` 中混合不同大小条目的情况,如首页信息流中的广告位、推荐商品等[^2]。 ### 数据更新优化:DiffUtil 的应用 当数据集发生变化时,直接调用 `notifyDataSetChanged()` 可能会导致不必要的重绘和重新绑定操作,影响性能。为此,Android 提供了 `DiffUtil` 工具类来计算新旧数据之间的差异,并仅更新必要的部分。关键在于实现 `areItemsTheSame` 和 `areContentsTheSame` 方法,以确定哪些项是相同的以及它们的内容是否发生了变化: ```java public class MyDiffCallback extends DiffUtil.ItemCallback<MyItem> { @Override public boolean areItemsTheSame(@NonNull MyItem oldItem, @NonNull MyItem newItem) { return oldItem.getId() == newItem.getId(); } @Override public boolean areContentsThe相同(@NonNull MyItem oldItem, @NonNull MyItem newItem) { return oldItem.equals(newItem); } } ``` 通过 `DiffUtil.calculateDiff()` 计算出差异后,可以调用 `submitList()` 或类似方法将更新提交到 `RecyclerView.Adapter`,从而实现高效的数据刷新[^3]。 ### 轮播图控件的实现 为了构建一个功能完善的轮播图控件,通常会基于 `RecyclerView` 进行扩展。这包括自定义 `LayoutManager` 来控制子视图的位置、方向和动画效果,同时还需要实现自动循环播放逻辑、点击事件监听以及指示器同步等功能。具体来说,可以借助 `PagerSnapHelper` 或类似的辅助类帮助实现页面对齐效果,并结合定时任务定期切换当前页码。 此外,考虑到内存效率问题,应尽量减少每个条目的复杂度并合理利用缓存机制。例如,对于图片资源,建议采用 Glide 或 Picasso 等第三方库进行加载和缓存处理;而对于文本或其他静态内容,则可通过复用已有的 View 对象降低创建成本。 ### 常见问题与解决方案 1. **条目间距不一致**:确保所有 ItemDecoration 都正确设置了偏移量,或者检查 LayoutManager 是否有特殊配置。 2. **滚动卡顿**:优化 onBindViewHolder 内部的操作,避免在此处执行耗时任务,比如网络请求或数据库查询。 3. **无法响应点击事件**:确认 OnItemClickListener 是否被正确设置,并且 ViewHolder 中的 itemView 没有被覆盖或拦截触摸事件。 4. **数据更新异常**:使用 DiffUtil 替代 notifyDataSetChanged() 可以有效减少界面抖动现象,提高用户体验。 5. **初始化失败**:检查 XML 文件中 RecyclerView 的声明是否完整,以及关联的 Adapter 是否已经实例化并且绑定到了正确的 RecyclerView 上。 综上所述,掌握这些核心概念和技术细节有助于开发者更好地利用 `RecyclerView` 构建高性能且交互友好的 Android 应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值