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

Android 图片库之Glide框架之RecycleView使用以及RecycleView详解

程序员文章站 2022-06-01 16:52:09
...

RecycleView简介

RecyclerView 是Android L版本中新添加的一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好。

RecyclerView与ListView原理是类似的:都是仅仅维护少量的View并且可以展示大量的数据集。RecyclerView用以下两种方式简化了数据的展示和处理:


1.使用LayoutManager来确定每一个item的排列方式。


2.为增加和删除项目提供默认的动画效果。


你也可以定义你自己的LayoutManager和添加删除动画,RecyclerView项目结构如下:

Android 图片库之Glide框架之RecycleView使用以及RecycleView详解

Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定。

LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似)。







下面讲述RecycleView+Glide框架的详细知识。


Glide框架详解:https://blog.csdn.net/weixin_37730482/article/category/6875816



代码以及说明


1.item布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="80dp">


    <ImageView
        android:id="@+id/gliderecycleview_circleimageview"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="15dp"
        android:scaleType="fitXY"
        android:src="@mipmap/patient_ava" />


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_toRightOf="@+id/gliderecycleview_circleimageview">

        <TextView
            android:id="@+id/gliderecycleview_item_textview1"
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:ellipsize="end"
            android:gravity="center|left"
            android:singleLine="true"
            android:text="张三"
            android:textColor="@color/colorPrimary"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/gliderecycleview_item_textview2"
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:layout_below="@+id/gliderecycleview_item_textview1"
            android:ellipsize="end"
            android:gravity="center|left"
            android:singleLine="true"
            android:text="这个人很懒什么也没留下"
            android:textColor="@color/colorPrimary"
            android:textSize="14sp" />

    </RelativeLayout>


    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:layout_alignParentBottom="true"
        android:background="@color/colorPrimary"/>

</RelativeLayout>

注意:

1.RecycleView的Item父布局高度不要写成match_parent。


2.可以在Item的布局中设置RecycleView的间隔线,这样就可以不用在Java代码中设置。



2.MainActivity布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/activity_gliderecycleview_toplayout"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:background="#339BFF">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="20dp"
            android:gravity="center"
            android:text="RecyclerView页面"
            android:textColor="#FFFFFF"
            android:textSize="16sp" />

    </RelativeLayout>

    <LinearLayout
        android:id="@+id/activity_gliderecycleview_linearlayout"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_below="@+id/activity_gliderecycleview_toplayout"
        android:orientation="horizontal"
        android:weightSum="3">

        <Button
            android:id="@+id/activity_gliderecycleview_modebutton"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="列表" />

        <Button
            android:id="@+id/activity_gliderecycleview_addbutton"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:text="插入数据" />

        <Button
            android:id="@+id/activity_gliderecycleview_delbutton"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:text="删除数据" />
    </LinearLayout>

    <View
        android:id="@+id/activity_gliderecycleview_view"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_below="@+id/activity_gliderecycleview_linearlayout"
        android:background="#CCCCCC" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/activity_gliderecycleview_recycleview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/activity_gliderecycleview_view">

    </android.support.v7.widget.RecyclerView>


</RelativeLayout>

注意:

1.AndroidStudio中配置

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

2.RecycleView所在包android.support.v7.widget.RecyclerView。



3.Adapter

public class GlideRecycleViewAdapter extends RecyclerView.Adapter<GlideRecycleViewAdapter.ViewHolder> {

    private Activity activity;
    private Context context;
    private List<Student> list;
    private LayoutInflater mInflater;

    private RecycleViewAdapterInterface recycleViewAdapterInterface=null;
    public void setRecycleViewItemClickAndLongClick(RecycleViewAdapterInterface recycleViewAdapterInterface){
        this.recycleViewAdapterInterface=recycleViewAdapterInterface;
    }


    public GlideRecycleViewAdapter(Activity activity,Context context,List<Student> list){
        this.activity=activity;
        this.context=context;
        this.list=list;
        mInflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view=mInflater.inflate(R.layout.gliderecycleview_item, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.textView1.setText(list.get(position).getName() + "【" + (position + 1) + "】");
        holder.textView2.setText(list.get(position).getAge());
        String ava = list.get(position).getAva();
        if(!BooleanUtils.isEmpty(ava)){//头像不为空
            //文字显示颜色
            holder.textView1.setTextColor(context.getResources().getColor(R.color.colorPrimary));
            holder.textView2.setTextColor(context.getResources().getColor(R.color.colorPrimary));
            //获取 ava 对应的缓存文件
            File file=new GlideImageUtils(context).getCacheFile(ava);
            if(null!=file){//缓存文件不为空 直接加载file对应的图片
                Glide.with(activity)
                        .load(file)
                        .placeholder(R.mipmap.patient_ava)
                        .error(R.mipmap.patient_ava)
                        .transform(new GlideCircleTransform(activity))
                        .into(holder.circleImageView);
            }else{//缓存文件为空 加载url对应的图片
                Glide.with(activity)
                        .load(ava)
                        .placeholder(R.mipmap.patient_ava)
                        .error(R.mipmap.patient_ava)
                        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                        .transform(new GlideCircleTransform(activity))
                        .into(holder.circleImageView);
            }
        }else{//头像为空
            //文字显示颜色
            holder.textView1.setTextColor(context.getResources().getColor(R.color.colorAccent));
            holder.textView2.setTextColor(context.getResources().getColor(R.color.colorAccent));
            Glide.with(activity)
                    .load("http:www")
                    .placeholder(R.mipmap.patient_ava)
                    .error(R.mipmap.patient_ava)
                    .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                    .transform(new GlideCircleTransform(activity))
                    .into(holder.circleImageView);
        }

        /**
         * 捕获RecycleView的Item点击以及长按事件
         * */

        final int clickposition=position;
        //Item点击
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(null!=recycleViewAdapterInterface){
                    recycleViewAdapterInterface.OnItemCilck(v,clickposition);
                }
            }
        });
        //Item长按
        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if(null!=recycleViewAdapterInterface){
                    recycleViewAdapterInterface.OnItemLongCilck(v,clickposition);
                }
                return true;
            }
        });
    }

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

    /**
     * ViewHolder类
     * */

    class ViewHolder extends RecyclerView.ViewHolder{

        private ImageView circleImageView;
        private TextView textView1;
        private TextView textView2;

        public ViewHolder(View itemView) {
            super(itemView);
            circleImageView = itemView.findViewById(R.id.gliderecycleview_circleimageview);
            textView1 = itemView.findViewById(R.id.gliderecycleview_item_textview1);
            textView2 = itemView.findViewById(R.id.gliderecycleview_item_textview2);
        }
    }

    /**
     * 添加数据
     * */

    public void addData(Student student,int position) {
        list.add(position, student);
        notifyItemInserted(position);
        notifyItemRangeChanged(position,list.size());
    }

    /**
     * 删除数据
     * */

    public void removeData(int position) {
        list.remove(position);
        notifyItemRemoved(position);
        notifyItemRangeChanged(position,list.size());
    }


}

注意:

1.和ListView直接继承BaseAdapter不同。RecycleView的适配器

   继承RecyclerView.Adapter<GlideRecycleViewAdapter.ViewHolder>。


2.至少需要重写三个方法。

onCreateViewHolder方法:引入Item布局。

onBindViewHolder方法:获取数值。

getItemCount方法:获取列表Item条数。


3.与ListView不同,RecycleView没有直接提供Item点击以及Item长按事件。需要自己写。


3.1.自定义接口

/**
 * RecycleView Item点击以及长按事件
 * */

public interface RecycleViewAdapterInterface {

    void OnItemCilck(View view, int position);
    void OnItemLongCilck(View view,int position);

}

3.2.Adapter中初始化以及暴露外部调用方法


3.2.1.初始化(onBindViewHolder方法中)

        /**
         * 捕获RecycleView的Item点击以及长按事件
         * */

        final int clickposition=position;
        //Item点击
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(null!=recycleViewAdapterInterface){
                    recycleViewAdapterInterface.OnItemCilck(v,clickposition);
                }
            }
        });
        //Item长按
        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if(null!=recycleViewAdapterInterface){
                    recycleViewAdapterInterface.OnItemLongCilck(v,clickposition);
                }
                return true;
            }
        });


3.2.2.外部调用(全局)

    private RecycleViewAdapterInterface recycleViewAdapterInterface=null;
    public void setRecycleViewItemClickAndLongClick(RecycleViewAdapterInterface recycleViewAdapterInterface){
        this.recycleViewAdapterInterface=recycleViewAdapterInterface;
    }


4.删除和添加数据

RecycleView删除添加数据非常方便。

    /**
     * 添加数据
     * */

    public void addData(Student student,int position) {
        list.add(position, student);
        notifyItemInserted(position);
        notifyItemRangeChanged(position,list.size());
    }

    /**
     * 删除数据
     * */

    public void removeData(int position) {
        list.remove(position);
        notifyItemRemoved(position);
        notifyItemRangeChanged(position,list.size());
    }




4.Activity中使用

public class GlideRecycleViewActivity extends AppCompatActivity implements View.OnClickListener {

    private Button modebutton;
    private Button addbutton;
    private Button delbutton;
    private RecyclerView recyclerview;
    private GlideRecycleViewAdapter adapter;
    private List<Student> list;
    private int type = 0;
    private int addposition = 0;
    private int delposition = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gliderecycleview);
        onWindowbar();
        initData();
    }

    /**
     * 赋值
     */

    private void initData() {
        modebutton = findViewById(R.id.activity_gliderecycleview_modebutton);
        addbutton = findViewById(R.id.activity_gliderecycleview_addbutton);
        delbutton = findViewById(R.id.activity_gliderecycleview_delbutton);
        modebutton.setOnClickListener(this);
        addbutton.setOnClickListener(this);
        delbutton.setOnClickListener(this);

        recyclerview = findViewById(R.id.activity_gliderecycleview_recycleview);
        list = new ArrayList<>();
        Student student1 = new Student();
        student1.setName("詹姆斯");
        student1.setAva("XXX");
        student1.setAge(student1.getName() + ":很懒什么也没留下!");

        Student student2 = new Student();
        student2.setName("韦德");
        student2.setAva("XXX");
        student2.setAge(student2.getName() + ":很懒什么也没留下!");

        Student student3 = new Student();
        student3.setName("山东鲁能");
        student3.setAva("XXX");
        student3.setAge(student3.getName() + ":很懒什么也没留下!");

        Student student4 = new Student();
        student4.setName("保罗");
        student4.setAva("XXX");
        student4.setAge(student4.getName() + ":很懒什么也没留下!");

        Student student5 = new Student();
        student5.setName("安东尼");
        student5.setAva("XXX");
        student5.setAge(student5.getName() + ":很懒什么也没留下!");

        Student student6 = new Student();
        student6.setName("蒿俊闵");
        student6.setAva("XXX");
        student6.setAge(student6.getName() + ":很懒什么也没留下!");

        Student student7 = new Student();
        student7.setName("李霄鹏");
        student7.setAva("");
        student7.setAge(student7.getName() + ":没有上传头像!");

        for (int i = 0; i < 30; i++) {
            list.add(student1);
            list.add(student2);
            list.add(student3);
            list.add(student4);
            list.add(student5);
            list.add(student6);
            list.add(student7);
        }

        //2.设置LinearLayoutManager ListView
        recyclerview.setLayoutManager(new LinearLayoutManager(this));
        //3.设置ItemAnimator
        recyclerview.setItemAnimator(new DefaultItemAnimator());
        //4.设置固定大小
        recyclerview.setHasFixedSize(true);
        adapter = new GlideRecycleViewAdapter(this, this, list);
        recyclerview.setAdapter(adapter);

        /**
         * RecycleView滚动监听是开始加载Glide还是暂停加载Glide
         * */

        recyclerview.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                switch (newState) {
                    case SCROLL_STATE_SETTLING://滚动
                        Glide.with(GlideRecycleViewActivity.this).pauseRequests();//停止Glide加载图片
                        break;
                    case SCROLL_STATE_DRAGGING://拖动
                        Glide.with(GlideRecycleViewActivity.this).pauseRequests();//停止Glide加载图片
                        break;
                    case SCROLL_STATE_IDLE://空闲
                        Glide.with(GlideRecycleViewActivity.this).resumeRequests();//开始Glide加载图片
                        break;
                    default://其他
                        Glide.with(GlideRecycleViewActivity.this).pauseRequests();//停止Glide加载图片
                        break;
                }
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
            }
        });

        /**
         * Item点击以及长按监听
         * */

        if (null != adapter) {
            adapter.setRecycleViewItemClickAndLongClick(new RecycleViewAdapterInterface() {
                @Override
                public void OnItemCilck(View view, int position) {
                    if (null != list) {
                        String name = list.get(position).getName();
                        Toast.makeText(GlideRecycleViewActivity.this, "点击:" + name, Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void OnItemLongCilck(View view, int position) {
                    if (null != list) {
                        String name = list.get(position).getName();
                        Toast.makeText(GlideRecycleViewActivity.this, "长按:" + name, Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }

    /**
     * 各种点击事件的View
     */

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.activity_gliderecycleview_modebutton://变换模式
                type++;
                if (type == 0) {//列表
                    modebutton.setText("列表");
                    recyclerview.setLayoutManager(new LinearLayoutManager(GlideRecycleViewActivity.this));
                } else if (type == 1) {//网格
                    modebutton.setText("网格");
                    recyclerview.setLayoutManager(new GridLayoutManager(GlideRecycleViewActivity.this, 4));
                } else if (type == 2) {//横向列表
                    modebutton.setText("横向列表");
                    recyclerview.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL));
                } else {
                    type = 0;
                    modebutton.setText("列表");
                    recyclerview.setLayoutManager(new LinearLayoutManager(GlideRecycleViewActivity.this));
                }
                break;
            case R.id.activity_gliderecycleview_addbutton://添加数据
                if (null != adapter) {
                    addposition++;
                    Student student = new Student();
                    student.setName("詹姆斯" + addposition);
                    student.setAva("http://cdspres.oss-cn-beijing.aliyuncs.com/avatar/80366a04e7874e4fa04a6ef8e68ab3751525391386176.png");
                    student.setAge(student.getName() + ":很懒什么也没留下!");
                    adapter.addData(student, addposition);
                }
                break;
            case R.id.activity_gliderecycleview_delbutton://删除数据
                if (null != adapter) {
                    delposition++;
                    adapter.removeData(delposition);
                }
                break;
            default:
                break;
        }
    }

    /**
     * onKeyDown方法
     */

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            finish();
            overridePendingTransition(0, R.anim.activity_right_open);
            return false;
        }
        return super.onKeyDown(keyCode, event);
    }

}

注意:

1.RecycleView的滚动事件最好是这样添加。

recyclerview.addOnScrollListener(new RecyclerView.OnScrollListener())

因为

recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener())

可能会出现空指针,且已过期。


另外RecycleView滚动事件 状态


SCROLL_STATE_SETTLING:滚动


SCROLL_STATE_DRAGGING:拖动


SCROLL_STATE_IDLE:空闲



2.目前SDK中提供了三种自带的LayoutManager


LinearLayoutManager:ListView列表


GridLayoutManager:GridView列表


StaggeredGridLayoutManager:纵向列表

recyclerview.setLayoutManager(new LinearLayoutManager(this));
recyclerview.setLayoutManager(new GridLayoutManager(GlideRecycleViewActivity.this, 4));//4:GridView一行显示几个Item
recyclerview.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL));2:纵向列表一页显示几行item

3.可设置RecycleView的Animator(动画效果,这里以默认为例)

recyclerview.setItemAnimator(new DefaultItemAnimator());


4.获取在Adapter中设置的RecycleView的Item点击以及长按事件。

        /**
         * Item点击以及长按监听
         * */

        if (null != adapter) {
            adapter.setRecycleViewItemClickAndLongClick(new RecycleViewAdapterInterface() {
                @Override
                public void OnItemCilck(View view, int position) {
                    if (null != list) {
                        String name = list.get(position).getName();
                        Toast.makeText(GlideRecycleViewActivity.this, "点击:" + name, Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void OnItemLongCilck(View view, int position) {
                    if (null != list) {
                        String name = list.get(position).getName();
                        Toast.makeText(GlideRecycleViewActivity.this, "长按:" + name, Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }