欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

浅谈RecyclerView(完美替代ListView,GridView)

程序员文章站 2024-02-28 18:14:28
android recyclerview 是android5.0推出来的,导入support-v7包即可使用。 个人体验来说,recyclerview绝对是一款功能强大的...

android recyclerview 是android5.0推出来的,导入support-v7包即可使用。

个人体验来说,recyclerview绝对是一款功能强大的控件。

首先总结下recyclerview的特点:

1.支持不同方向,不同排版模式,实现多种展现数据的形式,涵盖了listview,gridview,瀑布流等数据表现的形式

2.内部实现了回收机制,无需我们考虑view的复用情况

3.取消了onitemclick等点击事件,需要自己手动去写

那么让我们通过一些demo来了解recyclerview的基本使用

 android studio

build.gradle文件中 dependencies中添加

compile 'com.android.support:recyclerview-v7:22.+'

首先,要导入support-v7 包

import android.support.v7.widget.recyclerview;

recyclerview和listview的使用一样,都需要有对应的adapter,列表项布局,数据源

1.先写主activity布局

可以看到recyclerview的标签

<android.support.v7.widget.recyclerview>

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  tools:context="com.xqx.superapp.app.android5activity">
 <button
  android:text="添加一个数据"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:onclick="btnadditem"
  />
 <button
  android:text="删除第一个"
  android:onclick="btnremoveitem"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"/>
 <android.support.v7.widget.recyclerview
 android:id="@+id/recycle_view"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 >
 </android.support.v7.widget.recyclerview>
</linearlayout>

菜单项布局,标准的上面图片,下面文字

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:gravity="center"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
 <imageview
  android:id="@+id/item_icon"
  android:src="@mipmap/machao_moqi"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"/>
 <textview
  android:id="@+id/item_title"
  android:text="名称"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  />
</linearlayout>

2.接下来就看activity代码了

首先看成员变量,与listview,gridview一样 标准三样, 控件,数据源,适配器

private list<string> data;  
private recyclerview recyclerview;
private myrecycleadapter adapter; //自定义适配器,继承recyclerview.adapter

接着我们必须要自定义一个viewholder,这个viewholder 必须要继承 recyclerview.viewholder

注意recyclerview不再提供onitemclick事件监听,所以需要我们自己手工写监听事件的方法

private static class viewholder extends recyclerview.viewholder implements view.onclicklistener {
 public imageview imageview;
 public textview textview;
 public viewholder(view itemview) {
  super(itemview);
  // 通常viewholder的构造,就是用于获取控件视图的
  imageview = (imageview) itemview.findviewbyid(r.id.item_icon);
  textview = (textview) itemview.findviewbyid(r.id.item_title);
  // todo 后续处理点击事件的操作
  itemview.setonclicklistener(this);

 }
 @override
 public void onclick(view v) {
  int position = getadapterposition();
  context context = imageview.getcontext();
  toast.maketext(context,"显示第"+position+"个项",toast.length_short).show();
 }
 }

再让我们看自定义适配器,注意这里的参数是viewholder,这个viewhodler是我们自己的,不要导入v7包下的viewholder,

之后要重写三个方法

private class myrecycleadapter extends recyclerview.adapter<viewholder>{ 
@override
public viewholder oncreateviewholder(viewgroup viewgroup, int i) {
 return null;
}
@override
public void onbindviewholder(viewholder viewholder, int i) {
}
@override
public int getitemcount() {
 return 0;
}
}

在自定义适配器myrecycleadapter中,首先要写一个构造方法,因为有数据源,所有构造方法里必然有list

private list<string> strings;
public myrecycleadapter(list<string> strings) {
 this.strings = strings;
}

然后就要重写三个方法了,

@override
public int getitemcount() {
 int ret = 0;
 if (strings != null) {
 ret = strings.size();
 }
 return ret;
}
 @override
 public viewholder oncreateviewholder(viewgroup viewgroup, int i) {
  viewholder ret = null;
  // 不需要检查是否复用,因为只要进入此方法,必然没有复用
  // 因为recyclerview 通过holder检查复用
  view v = layoutinflater.from(android5activity.this).inflate(r.layout.item_recycler, viewgroup, false);
  ret = new viewholder(v);
  return ret;
 }
@override
 public void onbindviewholder(viewholder viewholder, int i) {
  // 1.这里进行图片的加载
  viewholder.textview.settext(strings.get(i));
  int resid = r.mipmap.ic_launcher;
  int index = i%5;
  switch (index){
  case 0:
   resid = r.mipmap.a11;
   break;
  case 1:
   resid = r.mipmap.a33;
   break;
  case 2:
   resid = r.mipmap.a22;
   break;
  }
  viewholder.imageview.setimageresource(resid);
 }

完成自定义适配器和自定义viewholder的代码 就要进行recyclerview的使用了

首先 要了解  recyclerview.layoutmanager 这个属性

用于进行一个布局的设置,可以设置显示模式,listview或者gridview或者瀑布流

1.listview显示模式

// 1.线性布局
  linearlayoutmanager layoutmanager =
   new linearlayoutmanager(this, // 上下文
     linearlayout.vertical, //垂直布局,
     false);

浅谈RecyclerView(完美替代ListView,GridView)浅谈RecyclerView(完美替代ListView,GridView)

2.gridview显示模式

// 2.grid布局
 recyclerview.layoutmanager layoutmanager =
  new gridlayoutmanager(this,
     2, // 每行显示item项数目
     gridlayoutmanager.horizontal, //水平排列
     false
     );

浅谈RecyclerView(完美替代ListView,GridView)浅谈RecyclerView(完美替代ListView,GridView)

3.瀑布流显示模式

// 3.瀑布流
 recyclerview.layoutmanager layoutmanager =
  new staggeredgridlayoutmanager(3, // 每行显示的item项数目
   staggeredgridlayoutmanager.vertical); // 垂直排列

浅谈RecyclerView(完美替代ListView,GridView)

以上三种显示模式任意设置一种 就可以继续下面的代码

recyclerview.setlayoutmanager(layoutmanager);
 // 设置 recyclerview的adapter
 // 注意一定在设置了布局管理器之后调用
 adapter = new myrecycleadapter(data);
 recyclerview.setadapter(adapter);

最后记得加上“添加一个数据”,“删除第一个数据”的按钮响应事件。

首先看一下以往我们对listview,gridview等等的删除某一项的操作

先在数据源中删除该位置的数据,然后刷新整个适配器,那么就可能会造成列表闪屏的问题,还有为了删除添加一个数据项而操作整个数据源的问题

public void btnadditem(view view) {
 data.add(0,"time:"+system.currenttimemillis());
 adapter.notifydatasetchanged();
 }
 public void btnremoveitem(view view) {
 if (!data.isempty()) {
  data.remove(0);
 }
 adapter.notifyitemremoved(0);
 }

    而recyclerview为我们提供了一些新的实用的方法:

public void add(viewmodel item, int position) {
 items.add(position, item); //数据源先添加该数据
 notifyiteminserted(position); //在某个位置刷新即可
}
public void remove(viewmodel item) {
 int position = items.indexof(item);
 items.remove(position); //数据源先删除该数据
 notifyitemremoved(position); //在某个位置删除即可
}

完整代码:

package com.xqx.superapp.app;
import android.app.activity;
import android.content.context;
import android.support.v7.app.actionbaractivity;
import android.os.bundle;
import android.support.v7.widget.gridlayoutmanager;
import android.support.v7.widget.linearlayoutmanager;
import android.support.v7.widget.recyclerview;
import android.support.v7.widget.staggeredgridlayoutmanager;
import android.util.log;
import android.view.*;
import android.widget.*;
import java.util.linkedlist;
import java.util.list;
public class android5activity extends activity {
 private list<string> data;
 private recyclerview recyclerview;
 private myrecycleadapter adapter;
 @override
 protected void oncreate(bundle savedinstancestate) {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.activity_android5);
 data = new linkedlist<string>();
 recyclerview = (recyclerview) findviewbyid(r.id.recycle_view);
 // 设置布局管理器
 // 支持 单列线性排列,支持gridview模式,瀑布流模式
 // 1.线性布局
 linearlayoutmanager layoutmanager =
  new linearlayoutmanager(this, // 上下文     linearlayout.vertical, //垂直布局,
     false);
// // 2.grid布局
// recyclerview.layoutmanager layoutmanager =
//  new gridlayoutmanager(this,
//     2,
//     gridlayoutmanager.horizontal,
//     false
//     );
//
//  // 3.瀑布流
// recyclerview.layoutmanager layoutmanager =
//  new staggeredgridlayoutmanager(3,
//   staggeredgridlayoutmanager.vertical);
 recyclerview.setlayoutmanager(layoutmanager);
 // 设置 recyclerview的adapter
 // 注意一定在设置了布局管理器之后调用
 adapter = new myrecycleadapter(data);
 recyclerview.setadapter(adapter);
 }
 public void btnadditem(view view) {
 data.add(0,"time:"+system.currenttimemillis());
 adapter.notifydatasetchanged();
 }
 public void btnremoveitem(view view) {
 if (!data.isempty()) {
  data.remove(0);
 }
 adapter.notifyitemremoved(0);
 }
 /**
 * 继承recyclerview.adapter,用于显示数据
 * 需要定义并且使用 viewholder ,必须要使用
 */
 private class myrecycleadapter extends recyclerview.adapter<viewholder>{
 private list<string> strings;
 public myrecycleadapter(list<string> strings) {
  this.strings = strings;
 }
 @override
 public int getitemcount() {
  int ret = 0;
  if (strings != null) {
  ret = strings.size();
  }
  return ret;
 }
 @override
 public viewholder oncreateviewholder(viewgroup viewgroup, int i) {
  viewholder ret = null;
  // 不需要检查是否复用,因为只要进入此方法,必然没有复用
  // 因为recyclerview 通过holder检查复用
  view v = layoutinflater.from(android5activity.this).inflate(r.layout.item_recycler, viewgroup, false);
  ret = new viewholder(v);
  return ret;
 }
 @override
 public void onbindviewholder(viewholder viewholder, int i) {
  viewholder.textview.settext(strings.get(i));
  int resid = r.mipmap.ic_launcher;
  int index = i%5;
  switch (index){
  case 0:
   resid = r.mipmap.a11;
   break;
  case 1:
   resid = r.mipmap.a33;
   break;
  case 2:
   resid = r.mipmap.a22;
   break;
  }
  viewholder.imageview.setimageresource(resid);
 }
 }
 /**
 * 创建自己的viewholder ,必须要继承recyclerview.viewholder
 */
 private static class viewholder extends recyclerview.viewholder implements view.onclicklistener {
 public imageview imageview;
 public textview textview;
 public viewholder(view itemview) {
  super(itemview);
  // 通常viewholder的构造,就是用于获取控件视图的
  imageview = (imageview) itemview.findviewbyid(r.id.item_icon);
  textview = (textview) itemview.findviewbyid(r.id.item_title);
  // todo 后续处理点击事件的操作
  itemview.setonclicklistener(this);
 }
 @override
 public void onclick(view v) {
  int position = getadapterposition();
  context context = imageview.getcontext();
  toast.maketext(context,"显示第"+position+"个项",toast.length_short).show();
 }
 }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,同时也希望多多支持!