• ListView优化分页优化


    缘由

    我们在用ListView展现数据的时候。比如展现联系人,如果联系人太多就会出现卡的现象,比如如果有1000多条数据,从数据库里查询,然后装载到List容器这段时间是比较耗时的。虽然我们可以用asyncTask来单独开启一个子线程加载。一次查看那么多,未免有点多余。是否可以通过先装载30条数据,如果用户需要我们在继续查询并且展示后面的数据,这样一来可以提升。使用速率。

    实现方法

    1、数据库分页查询

    首先写SqlHelper指定每次查询数据库多少数据。代码如下

    /**
    * 分页查询黑名单
    *
    * @param limit
    * 限制数量
    * @param offset
    * 开始位置
    * @return
    */

    public List<BlackNumInfo> getPartBlackNum(int limit, int offset)
    {
    //查询返回的数据容器
    List<BlackNumInfo> blackNums = null;
    SQLiteDatabase db = dbHelper.getReadableDatabase();

    String[] columns = new String[] { NUM, MODE, ID };
    String selection = null;
    String[] selectionArgs = null;
    String groupBy = null;
    String having = null;
    String orderBy = null; // 排序功能
    String limitsr = offset + "," + limit; // 分页数据

    Cursor cursor = db.query(TABLE, columns, selection, selectionArgs, groupBy, having,
    orderBy, limitsr);
    //如果没有数据就返回View
    if (cursor.getCount() > 0)
    {
    blackNums = new ArrayList<BlackNumInfo>();
    }

    while (cursor.moveToNext())
    {
    String num = cursor.getString(0);
    int mode = cursor.getInt(1);
    int id = cursor.getInt(2);
    BlackNumInfo b = new BlackNumInfo(num, mode, id);
    blackNums.add(b);
    }

    db.close();
    dbHelper.close();
    return blackNums;
    }

    2. AsyncTask类的内部优化

    • 思路:每次开启一个异步任务查询数据。
    • 重置适配器中,数据容器的值,刷想适配器
    • ListView重绘
    /**
    * 异步加载
    */

    public void fillData()
    {
    new AsyncTask<String, Integer, String>()
    {

    // 程序运行前
    @Override
    protected void onPreExecute()
    {
    mLoadProgressBar.setVisibility(View.VISIBLE);
    // 显示加载进度
    super.onPreExecute();
    }

    // 程序运行时
    @Override
    protected String doInBackground(String... params)
    {
    // 查询 前30项的数据: 用子线程 ,
    if (mBlackNumList == null)
    {
    mBlackNumList = dao.getPartBlackNum(limit, offset);
    } else
    {
    // 如果不是第一次查询
    if (dao.getPartBlackNum(limit, offset) != null)
    {
    //把查询到的数据添加到容器中去
    mBlackNumList.addAll(dao.getPartBlackNum(limit, offset));
    }
    }

    return null;
    }

    // 运行后
    @Override
    protected void onPostExecute(String result)
    {
    //ProgressBar设置为不可见。
    mLoadProgressBar.setVisibility(View.INVISIBLE);

    if (adapter == null)
    {
    //第一次加载,创建适配器适配器
    adapter = new BlackNumAdapter(context, mBlackNumList);
    mBlackNumListView.setAdapter(adapter);
    } else
    {
    //第二次加载,适配器中容器数量
    adapter.setBlackNumList(mBlackNumList);
    //发送通知,适配器内容改变,从新加载
    adapter.notifyDataSetChanged();
    }
    }

    }.execute();
    }

    3.Adapter优化分页数据

    • 思路
    • convertView可回收视图的再次利用。
    • holderView类保存每次inflate出来View的子控件并保存在convertViewTag中。
    • 添加一个setDate()方法,重置容器数据

    public class BlackNumAdapter extends BaseAdapter
    {
    List<BlackNumInfo> mBlackNumList;
    Context context;
    BlackNumDao dao;

    public BlackNumAdapter(Context context, List<BlackNumInfo> mBlackNumList)
    {
    this.context = context;
    dao = new BlackNumDao(context);
    this.mBlackNumList = mBlackNumList;
    }

    public void setBlackNumList(List<BlackNumInfo> mBlackNumInfos)
    {
    this.mBlackNumList = mBlackNumInfos;
    }

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

    @Override
    public Object getItem(int position)
    {
    return mBlackNumList.get(position);
    }

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    {
    // 适配器的优化
    final BlackNumInfo numInfo = mBlackNumList.get(position);
    holderView hV = null;
    if (convertView == null)
    {
    hV = new holderView();
    convertView = LayoutInflater.from(context).inflate(R.layout.item_blacknum, parent,
    false);
    hV.modeTextView = (TextView) convertView.findViewById(R.id.tv_mode);
    hV.numberTextView = (TextView) convertView.findViewById(R.id.tv_number);
    hV.deleteImageView = (ImageView) convertView.findViewById(R.id.iv_deleteNumber);
    convertView.setTag(hV);
    } else
    {
    hV = (holderView) convertView.getTag();
    }

    hV.numberTextView.setText(mBlackNumList.get(position).getNum());

    String mode = "全部拦截";
    switch (numInfo.getMode())
    {
    case BlackNumDao.ALL:
    mode = "全部链接";
    break;
    case BlackNumDao.CLL:
    mode = "电话拦截";
    case BlackNumDao.SMS:
    mode = "短信拦截";
    default:
    break;
    }

    hV.modeTextView.setText(mode);
    hV.deleteImageView.setOnClickListener(new OnClickListener()
    {
    @Override
    public void onClick(View v)
    {
    // 删除功能
    dao.delete(numInfo.getNum() + "");
    mBlackNumList.remove(position);
    notifyDataSetChanged();
    }
    });
    return convertView;
    }

    }

    /**
    * 包装类
    * @author H_lang
    *
    */

    class holderView
    {
    public TextView modeTextView;
    public TextView numberTextView;
    public ImageView deleteImageView;
    }

    4.ListView滚动监听。

    • liseView设置滚动监听。
    • 重置分页查询的开始标度

    /**
    * 滚动状态改变的时候。
    */

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState)
    {
    // 根据滚动的状态来加载数据。
    if (scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL)
    {
    // 获得最后一次显示的数据
    int lastVisiblePosition = mBlackNumListView.getLastVisiblePosition();
    int size = mBlackNumList.size();

    if (lastVisiblePosition == size - 1)
    {
    //设置下次查询的开始位置。
    offset = limit + offset;
    fillData();
    }

    }

    }

    总结

    其中还是有许多的缺点。还有许多需要优化的功能。但是对于我现在学习的技术,没有想到更好的方法,希望以后我能继续优化,或者重写listView控件。

  • 相关阅读:
    BAT脚本批量调用Sql执行文件 (SqlServer 数据库)
    树莓派系统刻录到首次登陆等问题
    数据库视图的使用
    MQ配置安装
    PLSQL集合类型
    PLSQL-包函数存储过程
    Oracle 字段拆分替换在合并成一条
    ORACLE-EXP和IMP方法介绍
    javascript几个月前的时间
    返回顶部实现方式
  • 原文地址:https://www.cnblogs.com/ganwei/p/4803932.html
Copyright © 2020-2023  润新知