ListView的分批加载和分页加载

1、分批加载的原理:
其实分批加载是有DAO控制数据库返回固定条数的数据并显示在ListView的页面中。

public class CallSafeActivity2 extends BaseActivity implements OnClickListener{

    private TextView tv_title;
    private ImageView iv_left;
    private ImageView iv_right;
    private ListView list_view;
    private List<BlackNumber> mBlackNumbers;
    //表示每页多少条数据
    private int pageSize=20;
    //表示当前页面
    private int mCurrentPage=0;
    //表示总页数
    private int totalPage;
    private EditText et_page;
    private TextView current_count_page;
    private BlackNumberDao dao;

    /** * 初始化UI */
    @Override
    protected void initUI() {
        setContentView(R.layout.activity_call_safe2);
        list_view = (ListView) findViewById(R.id.list_view);
        et_page = (EditText) findViewById(R.id.et_page);
        current_count_page = (TextView) findViewById(R.id.current_count_page);

    }


    /** * 初始化标题栏 */
    @Override
    protected void initTiltBar() {
        tv_title = (TextView) findViewById(R.id.tv_title);
        iv_left = (ImageView) findViewById(R.id.iv_left);
        iv_right = (ImageView) findViewById(R.id.iv_right);
        tv_title.setText("黑名单管理");
        iv_left.setVisibility(View.INVISIBLE);
        iv_right.setVisibility(View.VISIBLE);
        iv_right.setOnClickListener(this);
    }

    /** * 初始化数据 */
    @Override
    protected void initData() {
        dao = new BlackNumberDao(this);
        //以下为普通的listView全部加载的方法
        //mBlackNumbers = dao.findAll();
        //CallSafeAdapter adapter = new CallSafeAdapter(mBlackNumbers, this);
        //list_view.setAdapter(adapter);

        //分页加载,totalPage代表总页数,mCurrentPage代表起始坐标
        totalPage = dao.getTotalNumber()/pageSize;
        current_count_page.setText(mCurrentPage+"/"+(totalPage-1));
        new Thread(){
            public void run(){
                //将查询到的数据添加到集合中
                mBlackNumbers= dao.findPar(pageSize, mCurrentPage);
                handler.sendEmptyMessage(0);
            }
        }.start();
    }
    Handler handler=new Handler(){
        public void handleMessage(Message msg) {
            CallSafeAdapter adapter=new CallSafeAdapter(mBlackNumbers, CallSafeActivity2.this);
            list_view.setAdapter(adapter);
        };
    };
    /** * listView适配器的定义 * @author dell * */
    private class CallSafeAdapter extends MyBaseAdapter<BlackNumber>{
        //MyBaseAdapter的构造方法
        public CallSafeAdapter(List<BlackNumber> mLists, Context mContext) {
            super(mLists, mContext);
        }

        private TextView tv_number;
        private TextView tv_mode;
        private ImageView iv_delete;
        private View view;
        private ViewHolder holder;

        //listView实现的核心方法
        public View getView(int position, View convertView, ViewGroup parent) {

            //用convertView可以把效率提高200%,但是每次复用的时候需要findViewById,pull逐行解析的时候比较费时间
            if (convertView==null) {
                view = View.inflate(CallSafeActivity2.this, R.layout.item_call_safe, null);

                //viewHold为静态类,效率可再提高50%,因为它的实现不再需要复用的时候再去findViewById,而是直接复用
                holder = new ViewHolder();

                holder.tv_number = (TextView) view.findViewById(R.id.tv_number);
                holder.tv_mode = (TextView) view.findViewById(R.id.tv_mode);
                holder.iv_delete = (ImageView) view.findViewById(R.id.iv_delete);

                view.setTag(holder);
            }else {
                view=convertView;
                holder = (ViewHolder) view.getTag();
            }

            holder.tv_number.setText(mLists.get(position).getNumber());
            String mode = mLists.get(position).getMode();
            if (mode.equals("1")) {
                holder.tv_mode.setText("全部拦截");
            } else if (mode.equals("2")) {
                holder.tv_mode.setText("电话拦截");
            } else if (mode.equals("3")) {
                holder.tv_mode.setText("短信拦截");
            }
            return view;
        }

    }
    /** * listView的优化,可以把效率提高50%。省去findViewById的过程,只需要获取一次对象 * @author dell * */
    static class ViewHolder{
        TextView tv_number;
        TextView tv_mode;
        ImageView iv_delete;
    }


    public void onClick(View v) {

    }
    /** * 上一页 */
    public void pre(View view){
        if (mCurrentPage<=0) {
            ToastUtils.showSafeToast(CallSafeActivity2.this, "已经是第一页了");
            return;
        }
        mCurrentPage--;
        initData();
    }
    /** * 下一页 */
    public void next(View view){
        if(mCurrentPage >= totalPage - 1 ){
            ToastUtils.showSafeToast(CallSafeActivity2.this, "已经是最后页了");
            return ;
        }
        mCurrentPage++;
        initData();
    }
    /** * 跳转到那页 * @param view */
    public void jump(View view){
        String str_page = et_page.getText().toString().trim();
        if(TextUtils.isEmpty(str_page)){
            ToastUtils.showSafeToast(CallSafeActivity2.this, "请输入页面");
        }else{
            //获取到页面
            int number = Integer.parseInt(str_page);
            //判断页面输入是否正确
            if(number < 0 || number > totalPage - 1){
                ToastUtils.showSafeToast(CallSafeActivity2.this, "请输入正确页面");

            }else{
                mCurrentPage = number;
                initData();
            }
        }
    }


}

对应的DAO类:

public class BlackNumberDao {

    private BlackNumberSQLiteOpenHelper helper;
    private SQLiteDatabase db;

    public BlackNumberDao(Context context) {
        helper = new BlackNumberSQLiteOpenHelper(context);
    }
    /** * 往数据库增加数据 * @param number * @param mode * @return */
    public boolean add(String number,String mode){
        db = helper.getWritableDatabase();
        ContentValues values=new ContentValues();
        values.put("number",number);
        values.put("mode", mode);
        long rawId = db.insert("blacknumber", null, values);
        if (rawId==-1) {
            //插入失败
            return false;
        }else {
            //插入成功
            return true;
        }
    }
    /** * 删除数据库中的数据 * @param number * @return */
    public boolean delete(String number){
        db = helper.getWritableDatabase();
        int rowNumber = db.delete("blacknumber", "number=?", new String[]{number});
        if (rowNumber==0) {
            return false;
        }else {
            return true;
        }
    }
    /** * 改变黑名单模式 * @param number * @param newmode * @return */
    public boolean changeNumberMode(String number,String newmode){
        db = helper.getWritableDatabase();
        ContentValues values=new ContentValues();
        values.put("mode", newmode);
        int rowNumber = db.update("blacknumber", values, "number=?", new String[]{number});
        if (rowNumber == 0) {
            return false;
        } else {
            return true;
        }
    }
    /** * 根据电话号码查询黑名单的模式 * * @param number * @return */
    public String find(String number) {
        String mode = "";
        SQLiteDatabase db = helper.getReadableDatabase();
        Cursor cursor = db.query("blacknumber", new String[] { "mode" },
                "number=?", new String[] { number }, null, null, null);
        if (cursor.moveToNext()) {
            mode = cursor.getString(0);
        }
        cursor.close();
        db.close();
        return mode;
    }
    /** * 查询所有数据 * @return */
    public List<BlackNumber> findAll(){
        List<BlackNumber> list=new ArrayList<BlackNumber>();
        db = helper.getWritableDatabase();
        Cursor cursor = db.query("blacknumber", new String[]{"number","mode"}, null , null, null, null, null);
        while (cursor.moveToNext()) {
            BlackNumber blackNumber = new BlackNumber();
            blackNumber.setNumber(cursor.getString(0));
            blackNumber.setMode(cursor.getString(1));
            list.add(blackNumber);
        }
        cursor.close();
        db.close();
        return list;
    }
    /** * 分页查询 * @param pageSize 每页加载多少条数据 * @param startIndex 每页的开始位置 * @return */
    public List<BlackNumber> findPar(int pageSize,int startIndex){
        List<BlackNumber> list = new ArrayList<BlackNumber>();
        db = helper.getWritableDatabase();
        Cursor cursor = db.rawQuery("select number,mode from blacknumber limit ? offset ?", new String[]{String.valueOf(pageSize),String.valueOf(startIndex*pageSize)});
        while (cursor.moveToNext()) {
            BlackNumber blackNumber = new BlackNumber();
            blackNumber.setNumber(cursor.getString(0));
            blackNumber.setMode(cursor.getString(1));
            list.add(blackNumber);
        }
        cursor.close();
        db.close();
        return list;
    }

    /** * 分批查询 * @param pageSize 每页加载多少条数据 * @param startIndex 每页的开始位置 * @return */
    public List<BlackNumber> findPar2(int pageSize,int startIndex){
        List<BlackNumber> list = new ArrayList<BlackNumber>();
        db = helper.getWritableDatabase();
        Cursor cursor = db.rawQuery("select number,mode from blacknumber limit ? offset ?", new String[]{String.valueOf(pageSize),String.valueOf(startIndex)});
        while (cursor.moveToNext()) {
            BlackNumber blackNumber = new BlackNumber();
            blackNumber.setNumber(cursor.getString(0));
            blackNumber.setMode(cursor.getString(1));
            list.add(blackNumber);
        }
        cursor.close();
        db.close();
        return list;
    }
    /** * 查询总条数 * @return */
    public int getTotalNumber(){
        db = helper.getWritableDatabase();
        Cursor cursor = db.rawQuery("select count(*) from blacknumber", null);
        cursor.moveToNext();
        int count = cursor.getInt(0);
        cursor.close();
        db.close();
        return count;
    }
}

2、分批加载原理与分页加载原理相同,不同在于判断ListView是否下拉到底部,然后再加载数据,有个刷新的过程,代码如下:

描 述 :实现分批加载,新增setOnScrollListener监听器,list_view.getLastVisiblePosition()方法

public class CallSafeActivity extends BaseActivity implements OnClickListener{

    private TextView tv_title;
    private ImageView iv_left;
    private ImageView iv_right;
    private ListView list_view;
    private List<BlackNumber> mBlackNumbers;
    //表示每页多少条数据
    private int maxCount=20;
    //表示当前页面
    private int startIndex=0;
    //表示总页数
    private int totalNumber;
    private BlackNumberDao dao;

    /** * 初始化UI */
    @Override
    protected void initUI() {
        setContentView(R.layout.activity_call_safe);
        list_view = (ListView) findViewById(R.id.list_view);
        list_view.setOnScrollListener(new OnScrollListener() {
            //触屏状态改变的时候回调用(静止到滚动。。。)
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState) {
                //惯性滑动调用的方法
                case OnScrollListener.SCROLL_STATE_FLING:

                    break;
                //当滚动静止时调用的方法
                case OnScrollListener.SCROLL_STATE_IDLE:
                    int lastVisiblePosition = list_view.getLastVisiblePosition();

                    //判断当前的最后一条数据是不是服务器返回的最后一条数据
                    if (lastVisiblePosition==mBlackNumbers.size()-1) {
                        //从服务器分批加载数据
                        startIndex+=maxCount;
                        if (startIndex>=totalNumber) {
                            ToastUtils.showSafeToast(CallSafeActivity.this, "已经没有更多的数据了");
                            return;
                        }
                        initData();
                    }
                    break;
                //当触摸屏幕的时候调用的方法
                case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:

                    break;
                default:
                    break;
                }
            }
            //触摸到屏幕会调用
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {

            }
        });

    }


    /** * 初始化标题栏 */
    @Override
    protected void initTiltBar() {
        tv_title = (TextView) findViewById(R.id.tv_title);
        iv_left = (ImageView) findViewById(R.id.iv_left);
        iv_right = (ImageView) findViewById(R.id.iv_right);
        tv_title.setText("黑名单管理");
        iv_left.setVisibility(View.INVISIBLE);
        iv_right.setVisibility(View.VISIBLE);

        //为添加黑名单设置点击事件
        iv_right.setOnClickListener(this);
    }

    /** * 初始化数据 */
    @Override
    protected void initData() {
        dao = new BlackNumberDao(this);

        //分页加载,totalPage代表总页数,mCurrentPage代表起始坐标
        totalNumber = dao.getTotalNumber();

        new Thread(){
            public void run(){
                // 判断当前的集合是否有数据。如果没有数据那么就把数据库的20条数据添加进去
                if (mBlackNumbers==null) {
                    mBlackNumbers= dao.findPar2(maxCount, startIndex);
                }else {
                    //如果已经有了数据,防止覆盖
                    mBlackNumbers.addAll(dao.findPar2(maxCount, startIndex));
                }
                handler.sendEmptyMessage(0);
            }
        }.start();
    }
    private CallSafeAdapter adapter;
    Handler handler=new Handler(){
        public void handleMessage(Message msg) {
            if (adapter==null) {
                adapter = new CallSafeAdapter(mBlackNumbers, CallSafeActivity.this);
                list_view.setAdapter(adapter);
            }else {
                //刷新当前界面的数据
                adapter.notifyDataSetChanged();
            }
        };

    };
    private AlertDialog dialog;
    /** * listView适配器的定义 * @author dell * */
    private class CallSafeAdapter extends MyBaseAdapter<BlackNumber>{
        //CallSafeAdapter的构造方法
        public CallSafeAdapter(List<BlackNumber> mLists, Context mContext) {
            super(mLists, mContext);
        }

        private TextView tv_number;
        private TextView tv_mode;
        private ImageView iv_delete;
        private View view;
        private ViewHolder holder;

        //listView实现的核心方法
        public View getView(final int position, View convertView, ViewGroup parent) {

            //用convertView可以把效率提高200%,但是每次复用的时候需要findViewById,pull逐行解析的时候比较费时间
            if (convertView==null) {
                view = View.inflate(CallSafeActivity.this, R.layout.item_call_safe, null);

                //viewHold为静态类,效率可再提高50%,因为它的实现不再需要复用的时候再去findViewById,而是直接复用
                holder = new ViewHolder();

                holder.tv_number = (TextView) view.findViewById(R.id.tv_number);
                holder.tv_mode = (TextView) view.findViewById(R.id.tv_mode);
                holder.iv_delete = (ImageView) view.findViewById(R.id.iv_delete);

                view.setTag(holder);
            }else {
                view=convertView;
                holder = (ViewHolder) view.getTag();
            }

            holder.tv_number.setText(mLists.get(position).getNumber());
            String mode = mLists.get(position).getMode();
            if (mode.equals("1")) {
                holder.tv_mode.setText("全部拦截");
            } else if (mode.equals("2")) {
                holder.tv_mode.setText("电话拦截");
            } else if (mode.equals("3")) {
                holder.tv_mode.setText("短信拦截");
            }
            //获取到黑名单的电话号码
            final String number = mLists.get(position).getNumber();
            //删除黑名单的电话号码
            holder.iv_delete.setOnClickListener(new OnClickListener() {

                public void onClick(View v) {
                    //根据电话号码删除数据
                    boolean result = dao.delete(number);
                    //如果返回true说明删除成功
                    if (result) {
                        //将当前的对象从集合里边删除
                        mBlackNumbers.remove(position);
                        //刷新界面
                        adapter.notifyDataSetChanged();
                        ToastUtils.showSafeToast(CallSafeActivity.this, "删除成功");
                    }else {
                        ToastUtils.showSafeToast(CallSafeActivity.this, "删除失败");
                    }
                }
            });
            return view;
        }

    }
    /** * listView的优化,可以把效率提高50%。省去findViewById的过程,只需要获取一次对象 * @author dell * */
    static class ViewHolder{
        TextView tv_number;
        TextView tv_mode;
        ImageView iv_delete;
    }
    /** * 返回键 */
    @Override
    public void onBackPressed() {
        SystemInfo.startActivity(this, MainActivity.class);
        super.onBackPressed();
    }

    /** * 添加黑名单 */
    public void onClick(View v) {
        AlertDialog.Builder builder = new Builder(this);
        final View view = View.inflate(this, R.layout.dialog_add_black_number, null);
        //黑名单电话
        final TextView et_number = (TextView) view.findViewById(R.id.et_number);
        //确定
        Button bt_ok = (Button) view.findViewById(R.id.bt_ok);
        //取消
        Button bt_cancel = (Button) view.findViewById(R.id.bt_cancel);
        //电话拦截
        final CheckBox cb_phone = (CheckBox) view.findViewById(R.id.cb_phone);
        //短信拦截
        final CheckBox cb_sms = (CheckBox) view.findViewById(R.id.cb_sms);

        //取消的点击事件
        bt_cancel.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                dialog.dismiss();
            }
        });

        //确定的点击事件
        bt_ok.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                //获取到黑名单电话号码
                String str_number = et_number.getText().toString().trim();
                //如果当前黑名单号码设置为空,就提示用户输入电话号码
                if (TextUtils.isEmpty(str_number)) {
                    ToastUtils.showSafeToast(CallSafeActivity.this, "请输入电话号码");
                    return;
                }

                /** * 1 电话拦截 + 短信拦截(全部拦截) 2 电话拦截 3短信拦截 */
                String mode;
                //判断当前的电话号码和短信是否被勾选
                if (cb_phone.isChecked()&&cb_sms.isChecked()) {
                    //全部拦截
                    mode="1";
                }else if (cb_phone.isChecked()) {
                    //电话拦截
                    mode="2";
                }else if (cb_sms.isChecked()) {
                    //短信拦截
                    mode="3";
                }else{
                    ToastUtils.showSafeToast(CallSafeActivity.this, "请勾选拦截模式");
                    return;
                }
                BlackNumber blackNumber = new BlackNumber();    

                blackNumber.setNumber(str_number);
                blackNumber.setMode(mode);

                //判断当前是否添加成功——数据库
                boolean result = dao.add(str_number, mode);
                //如果true说明添加成功,刷新界面
                if (result) {
                    mBlackNumbers.add(0, blackNumber);
                    adapter.notifyDataSetChanged();
                    ToastUtils.showSafeToast(CallSafeActivity.this, "添加成功");
                }else{
                    ToastUtils.showSafeToast(CallSafeActivity.this, "添加失败");
                }
                dialog.dismiss();
            }
        });
        builder.setView(view);
        dialog = builder.show();
    }

}

你可能感兴趣的:(数据库,ListView)