【android】RecyclerView的使用

看这里
这里写图片描述

RecyclerView

用于在有限的窗口展示大量的数据集。可以通过设置它提供的不同 LayoutManager (控制显示的方式)、ItemDecoration (控制 Item 间的间隔,可绘制)、ItemAnimator (控制 Item 增删的动画)实现一些效果。

可以看出,相比 ListView ,RecyclerView在功能上没有什么大的不同,不同之处在于实现了高度的解耦,给予开发人员充分的自由,所以可以用这个控件实现 ListView、 GirdView,瀑布流等效果。

基础功能使用:

mRecyclerView = findView(R.id.id_recyclerview);
//设置布局管理器
mRecyclerView.setLayoutManager(layout);
//设置adapter
mRecyclerView.setAdapter(adapter)
//设置Item增加、移除动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(
                getActivity(), DividerItemDecoration.HORIZONTAL_LIST));

一个小例子

1、在 build.gradle 中导入包

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

2、写布局文件

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.chandelier.recyclerview.MainActivity">
        <android.support.v7.widget.RecyclerView
            android:id = "@+id/recyclerViewId"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

</RelativeLayout>

item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/pic_id"
        android:scaleType="centerCrop"
        android:layout_marginTop="5dp"
        android:layout_marginEnd="5dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

3、实现:

MainActivity.java:

package com.chandelier.recyclerview;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private static String TAG ="MainActivity";
    private RecyclerView recyclerView;
    private myAdapter mAdapter;
    private int lastVisibleItem ;
    private LinearLayoutManager linearLayoutManager;
    private okhttpClass okhttp;
    private int page = 1;
    private List<picRes>  more;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            okhttp = new okhttpClass();
        } catch (IOException e) {
            e.printStackTrace();
        }
        more= new ArrayList<>();//用来存放要加载的 Item(在这里是图片)对象(主要是url)
        initView();//初始化布局
        setListener();//设置监听事件
        new GetData().execute("http://gank.io/api/data/福利/10/1");//先加载一些 Item
    }
    private void initView(){
        recyclerView = (RecyclerView)findViewById(R.id.recyclerViewId);
        linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
    }

    private void setListener(){
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE
                        && lastVisibleItem +2>=linearLayoutManager.getItemCount()) {
                    new GetData().execute("http://gank.io/api/data/福利/10/"+(++page));
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
            }
        });
    }
    private class GetData extends AsyncTask<String, Integer, String> {

        @Override
        protected String doInBackground(String... params) {
            String responce = null;
            try {
                responce = okhttp.getOp(params[0]);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return responce;
        }

        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            if(!TextUtils.isEmpty(result)){

                JSONObject jsonObject;
                JSONArray jsonarray = new JSONArray();
                int count = 0;

                try {
                    jsonObject = new JSONObject(result);
                    jsonarray = jsonObject.getJSONArray("results");
                    count = jsonarray.length();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                String[] shujus = new String[count];


                for (int x = 0; x < count; x++){
                    try {
                        shujus[x] = jsonarray.getJSONObject(x).getString("url");
                        Log.i(TAG,"shujus["+x+"]:"+shujus[x]);
                        picRes pic = new picRes(shujus[x]);
                        more.add(pic);
                        Log.i(TAG,"将pic加入到more中:"+x);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }

                if(mAdapter==null){
                    mAdapter = new myAdapter(MainActivity.this,more);
                    Log.i(TAG,"new 一个 myAdapter。");
                    recyclerView.setAdapter(mAdapter);
                    Log.i(TAG,"设置好 一个 myAdapter。");
                }else{
                    mAdapter.notifyDataSetChanged();
                }
            }
        }
    }
}

GetData:继承自 AyncTask,主要重写了两个方法。

  • doInBackground(String... params):这个里面的代码在子线程中执行,执行一些耗时操作,这里主要使用 okHttp 进行网络请求,这里我对 okhttp 进行了小小的封装,下面会写到。
  • onPostExecute(String result):这个方法是当后台任务执行完毕并通过 return 返回时调用。在这个方法里我主要是对网络请求返回的数据进行解析,将图片的url 存储到 picRes 中,picRes 会在下面贴,就是用来存储 Item 信息的一个类。并且构造一个适配器,并为 recyclerView 设置该适配器。

setListener():这个方法里主要是做当用户滑动屏幕时,剩下的 item 少于两个时,自动加载下一页的工作。注意:添加了监听器不要忘记清除。

  • onScrolled (RecyclerView recyclerView,int dx,int dy):当滚动完成的时候,会调用此方法,第一个参数,表示哪一个 RecyclerView 会被调用;第二个参数表示水平滚动量;第三个参数垂直滚动量。
  • onScrollStateChanged (RecyclerView recyclerView,int newState):RecyclerView 的滚动状态发生改变的时候,该方法会被回调。第二个参数表示更新的滚动状态,有三种:
    • SCROLL_STATE_IDLE:RecyclerView 目前不滚动。
    • SCROLL_STATE_DRAGGING:RecyclerView 当前正在被外部输入拖动,例如用户触摸输入。
    • SCROLL_STATE_SETTLING:RecyclerView 目前正在移动到最终位置,而不再外部控制下。

这里面的 okhttpclass :

package com.chandelier.recyclerview;

import android.util.Log;

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;

import java.io.IOException;


public class okhttpClass {
    OkHttpClient mOkHttpClient;
    String TAG = "okhttpClass";
    public okhttpClass() throws IOException {
        Log.i(TAG,"in okhttpClass!");
        mOkHttpClient = new OkHttpClient();
    }
    public String getOp(String url) throws IOException{
        Log.i(TAG,"in getOp!");
        Request request = new Request.Builder().url(url).build();
        Response response = mOkHttpClient.newCall(request).execute();
        Log.i(TAG,"get responce");
        String str;
        if (response.isSuccessful()){
            ResponseBody responceBody = response.body();
            str = responceBody.string();
        }else{
            return "error";
        }
        return str;
    }
}

picRes :

package com.chandelier.recyclerview;

public class picRes{
    private String url;//图片地址

    public picRes(String url){
        this.url = url;
    }
    public String getUrl() {
        return url;
    }

}

myAdapter:

package com.chandelier.recyclerview;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.squareup.picasso.Picasso;

import java.util.List;

public class myAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<picRes> data;
    private LayoutInflater inflater;
    private Context context;

    public myAdapter(Context context,List<picRes> data) {
        this.context = context;
        this.data = data;
        inflater= (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public class myViewHolder extends RecyclerView.ViewHolder{
        public ImageView iv;

        public myViewHolder(View itemView) {
            super(itemView);
            iv= (ImageView) itemView.findViewById(R.id.pic_id);
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = inflater.inflate(R.layout.item, parent, false);
        return new myViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        Picasso.with(context).load(data.get(position).getUrl()).into(((myViewHolder)holder).iv);
    }

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

}

先看看重写的方法吧

  • int getItemCount():返回适配器中数据集中的 Item 的总数。
  • void onBindViewHolder(RecyclerView.ViewHolder holder, int position):由 RecyclerView 调用来在指定的位置显示数据,这个方法应该在定的位置更新 itemView 的内容。
    • 请注意,与ListView不同,如果 item 的位置在数据集中更改,则 RecyclerView 将不会再次调用这个方法,除非 item 本身无效或者新的位置无法确定。因此,我们应该只在获取此方法中的相关数据 item 时使用 position 这个参数,并且不应该保留这个参数的副本。如果我们在之后需要一个 item 的 position (比如在监听器中),应该使用 getAdapaterPosition() 方法。如果适配器可以处理有效的数据,就重写此方法。
    • 所以在这个方法中,我做的操作是将图片加载到 ViewHolder 中。这里使用到了 Picasso,picasso 是 Square 公司开源的一个 android图形缓存库,可以实现图片下载和缓存的功能,就像这个方法中,仅仅用一行代码就能实现图片的异步加载。他还解决了 android 中加载图片时需要解决的一些常见问题。后面我可能会写一篇博客详细说明,吧。
  • RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType):当 RecyclerView 一个新的 ViewHolder 代表一个指定类型的 Item 时调用。一个新的 ViewHolder 应该以一个新的View,即可以代表给定类型的 item来构建。我们可以手动创建一个新的 View, 也可以从 xml 布局文件中 inflate 他,这里我使用的就是 inflate 。创建的 ViewHolder 将用于 onBindViewHolder() 中显示适配器的 item。由于它将重新用于在数据集中显示不同的项目,所以缓存对视图子视图的引用是以一个好主意,以避免不必要的 findViewById(int) 调用。

源码地址:https://github.com/Chandelierr/recyclerview

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值