Android控件ListView优化及数据分页加载

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_29675423/article/details/86084298

ListView的缓存机制

listView在使用过程中需要注意item view的显示与缓存机制,即屏幕内显示,滑出屏幕就被会收到缓存,避免每次调用getView时都是通过inflate创建一个新的View对象,同时避免又在此view中通过findViewById找到对应的控件,利用ListView的缓存机制实现view的复用。

将数据放入ListView中显示,需要建立数据源与ListView之间的适配关系,也就是需要自定义适配器。

数据源:学生(姓名,班级,年龄)

public class Student {
    private String name;
    private String clas;
    private int age;

    public Student(String name, String clas, int age) {
        this.name = name;
        this.clas = clas;
        this.age = age;
    }

    public Student(){

    }

    public String getName() {
        return name;
    }

    public String getClas() {
        return clas;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setClas(String clas) {
        this.clas = clas;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

ListView:样式layout.item_student

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/tvName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tvClass"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tvAge"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

适配器:ListAdapter

这里以继承自BaseAdapter为例:

重写的方法有:

getCount():返回适配器对象关联的数据源中元素的个数;

getItem():根据指定的position返回索引位的数据对象;

getItemId():根据指定的索引位返回指定条目对应的行号;

getView(int position, View convertView, ViewGroup parent):当绘制ListView中的每一个item时自动调用的方法,绘制多少个item就会调用多少次;

public class ListAdapter extends BaseAdapter {

    private Context context;
    private  ArrayList<Student> list;
    
    public ListAdapter(Context context,  ArrayList<Student> list) {
        this.context = context;
        this.list = list;
    }

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

    @Override
    public Student getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder;

        if(convertView == null){
            convertView = LayoutInflater.from(context).inflate(R.layout.item_student, null);
            holder = new ViewHolder();
            holder.tvName = (TextView) convertView.findViewById(R.id.tvName);
            holder.tvClass = (TextView) convertView.findViewById(R.id.tvClass);
            holder.tvAge = (TextView)convertView.findViewById(R.id.tvAge);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }

        Student student =  getItem(position);
        holder.tvAge.setText(String.valueOf(student.getAge()));
        holder.tvClass.setText(student.getClas());
        holder.tvName.setText(student.getName());
        return convertView;
    }


    class ViewHolder{
        public TextView tvName;
        public TextView tvClass;
        public TextView tvAge;
    }

}

listView使用

布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context=".CursorActivity">
    <ListView
        android:id="@+id/lvCursor"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>

</android.support.constraint.ConstraintLayout>

主程序调用,students为数据集,listView为列表。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cursor);
        listView = findViewById(R.id.lvCursor);
        initAdapter();
        listView.setAdapter(adapter);
    }
     private void initAdapter() {
            adapter = new ListAdapter(this, students);
    }

ListView数据分页加载

上面数据集量很大时,需要分页进行加载,一次显示一定数量。

我们需要获取用户下拉到最后一个item的动作时,对数据进行加载,并对list进行更新。

设置每页数据数量 size

记录当前页数 page

用以确定当前加载到的数据节点。通过page*size确定

判断是否有数据需要加载 hasmore

可以通过当前获取到的数据的数量是不是比size小,如果不足size,说明数据全部加载完毕,没有更多数据需要加载。

判断加载的条件:

hasMore && view.getLastVisiblePosition() == view.getCount()-1 && scrollState == SCROLL_STATE_IDLE

 listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                Log.i("数据表信息","getLatVisiblePosition:"+ view.getLastVisiblePosition()+
                        "  get count = " + view.getCount());
                      //到最后一个item ,滑动停止,有更多数据可以加载 
                if(hasMore && view.getLastVisiblePosition() == view.getCount()-1 && scrollState == SCROLL_STATE_IDLE){
                    mCurrPage++;
                    getData();//加载
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });

获取新的数据

//分页加载数据代码,从mCurrNum = page*size开始,加载size个数据
        //以下为伪代码,根据数据源决定
        {
        	//get 数据
        	dataset = get data from mCurrNum to mCurrNum+size;
        	//添加进数据源lists中
        	lists.adds(dataset);
		}

更新列表

adapter.notifyDataSetChanged();

整体代码:

public class CursorActivity extends AppCompatActivity {

    private ListView listView;
    private ListAdapter adapter;

    private int mCurrPage = 0;//记录当前页
    private  int mSizePage = 10;//每页数据数量
    private boolean hasMore = true;//判断是否有更多数据需要加载

    ArrayList<Student> students = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cursor);
        listView = findViewById(R.id.lvCursor);
        initAdapter();//初始化适配器
        configList();//配置下拉加载更多数据
        listView.setAdapter(adapter);
        getData();//加载数据
    }

    /**
     * 滑动到底自动加载数据
     */
    private void configList() {
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                Log.i("数据表信息","getLatVisiblePosition:"+ view.getLastVisiblePosition()+
                        "  get count = " + view.getCount());
                      //非常重要的判断条件  
                if(hasMore && view.getLastVisiblePosition() == view.getCount()-1 && scrollState == SCROLL_STATE_IDLE){
                    mCurrPage++;
                    getData();
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });
    }


    private void initAdapter() {
            adapter = new ListAdapter(this, students);
    }

    /**
     * 加载你自己的数据
     * @return
     */
    private ArrayList<Student> getData() {
        int mCurrNum = mCurrPage * mSizePage;
        int offset = mSizePage;
        Log.i("数据表信息", "mCurr:"+mCurrNum+" moffset:"+offset);
        //分页加载数据代码,从mCurrNum开始,加载offset个数据
        //以下为伪代码,根据数据源决定
        {
        	//get 数据
        	dataset = get data from mCurrNum to mCurrNum+offset;
        	//添加进数据源students中
        	students.adds(dataset);
		}

        //判断是否还有更多的数据需要加载
        if(dataset.getCount() < offset){
            hasMore = false;
        }

        //更新列表
        adapter.notifyDataSetChanged();
        return students;
    }

}

猜你喜欢

转载自blog.csdn.net/sinat_29675423/article/details/86084298
今日推荐