使用游标带的ListView适配器大量数据的 [英] Using Cursor with ListView adapter for a large amount of data

查看:104
本文介绍了使用游标带的ListView适配器大量数据的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是自定义的CursorAdapter从SQLite数据库中获取数据,并显示在一个列表视图。该数据库包含约8.000行2列。所以我在寻找一种方式来查询和显示所有的数据尽可能快。我已经做到了这一点与AsyncTask的这里是code:

 私有类prepareAdapter延伸的AsyncTask<虚空,虚空,CustomCursorAdapter> {

 @覆盖
 在preExecute保护无效(){
     dialog.setMessage(等待);
     dialog.setIndeterminate(真正的);
     dialog.setCancelable(假);
     dialog.show();


     Log.e(TAG,Po​​sle月mAdapter);
 }

 @覆盖
 保护CustomCursorAdapter doInBackground(空...未使用){

   光标光标= myDbNamesHelper.getCursorQueryWithAllTheData();
   mAdapter.changeCursor(光标);
   startManagingCursor(光标);
   Log.e(时间,posle开始管理光标​​+将String.valueOf(SystemClock.elapsedRealtime() - 原料与材料)+毫秒);
     原料与材料= SystemClock.elapsedRealtime();

     mAdapter.initIndexer(光标);
     返回mAdapter;
 }

 保护无效onPostExecute(CustomCursorAdapter结果){

     TabFirstView.this.getListView()setAdapter(结果)。
     Log.e(时间,posle adapterSet+将String.valueOf(SystemClock.elapsedRealtime() - 原料与材料)+毫秒);
    原料与材料= SystemClock.elapsedRealtime();
     dialog.dismiss();
 }
 

}

这工作不错,除了一部分,当我需要的结果集到一个适配器。我已经做了一段时间的测试,它需要aprox的700毫秒,使其过去的startManagingCursor。问题是,它需要大约7秒钟,使过去的setAdapter(结果),这是在UI线程中运行,所以它使我的应用程序没有响应(进度对话框冻结有时是应用程序)。如何使这次少了?我可以让这也是在后台或任何方式,以提高响应速度跑?

TNX。

 公共类CustomCursorAdapter扩展SimpleCursorAdapter实现OnClickListener,SectionIndexer,可筛选,
                                    android.widget.AdapterView.OnItemClickListener {

    私人上下文的背景下;
    私人诠释布局;
    私人AlphabetIndexer alphaIndexer;

    公共CustomCursorAdapter(上下文的背景下,INT布局,光标C,的String []从,INT []键){
        超(背景下,布局,C,从,到);
        this.context =背景;
        this.layout =布局;

    }
    公共无效initIndexer(光标C){
         alphaIndexer =新AlphabetIndexer(C,c.getColumnIndex(DataBaseNamesHelper.COLUMN_NAME),ABCDEFGHIJKLMNOPQRSTUVWXYZ);
    }

    @覆盖
    公共查看NewView的(上下文的背景下,光标光标的ViewGroup父){

        光标C = getCursor();

        最后LayoutInflater充气= LayoutInflater.from(上下文);
        视图V = inflater.inflate(布局,父母,假);

        INT nameCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_NAME);

        字符串名称= c.getString(nameCol);

        / **
         *下一设置条目的名称。
         * /
        TextView的name_text =(TextView中)v.findViewById(R.id.name_entry);
        如果(name_text!= NULL){
            name_text.setText(名称);
        }

        INT favCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_FAVOURITED);
        INT最爱= c.getInt(favCol);

        INT idCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_ID);

        Button按钮=(按钮)v.findViewById(R.id.Button01);
        button.setOnClickListener(本);
        button.setTag(c.getInt(idCol));
        如果(喜欢的== 1){
            button.setVisibility(View.INVISIBLE);
        }
        其他button.setVisibility(View.VISIBLE);

        返回伏;
    }

    @覆盖
    公共无效bindView(视图V,上下文的背景下,光标C){

        INT nameCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_NAME);

        字符串名称= c.getString(nameCol);

        / **
         *下一设置条目的名称。
         * /
        TextView的name_text =(TextView中)v.findViewById(R.id.name_entry);
        如果(name_text!= NULL){
            name_text.setText(名称);
        }
        INT favCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_FAVOURITED);
        INT最爱= c.getInt(favCol);

        Button按钮=(按钮)v.findViewById(R.id.Button01);
        button.setOnClickListener(本);
        INT idCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_ID);
        button.setTag(c.getInt(idCol));
      // Log.e(最爱,将String.valueOf(最爱));
        如果(喜欢的== 1){
            button.setVisibility(View.INVISIBLE);
        }其他button.setVisibility(View.VISIBLE);
    }



    @覆盖
    公众诠释getPositionForSection(INT部分){
        返回alphaIndexer.getPositionForSection(部分);
    }

    @覆盖
    公众诠释getSectionForPosition(INT位置){
          返回alphaIndexer.getSectionForPosition(位置);
    }

    @覆盖
    公共对象[] getSections(){
          返回alphaIndexer.getSections();
    }
    @覆盖
    公共无效onItemClick(适配器视图<>为arg0,查看ARG1,INT ARG2,长ARG3){
        Log.e(项,点击,arg1.toString()+的位置>中+ ARG2);
    }

    @覆盖
    公共无效的onClick(视图v){
            如果(v.getId()== R.id.Button01){
                //Log.e("Button点击v.toString()+的位置>中+ v.getTag()的toString())。
                v.setVisibility(View.INVISIBLE);
                DataBaseNamesHelper数据库名称=新DataBaseNamesHelper(上下文);
                dbNames.setFavouritesFlag(v.getTag()的toString());
            }

        }



}
 

解决方案

究其原因,慢时加载的适配器内部调用的CursorAdapter使得以Cursor.getCount()。

在Android的游标延迟加载。结果不加载,直到需要它们。当的CursorAdapter调用getCount将()此强制查询要完全执行,结果计数。

下面是一对夫妇链接讨论这个非常问题。

<一个href="http://groups.google.com/group/android-developers/browse_thread/thread/c1346ec6e2310c0c">http://groups.google.com/group/android-developers/browse_thread/thread/c1346ec6e2310c0c

<一个href="http://www.androidsoftwaredeveloper.com/2010/02/25/sqlite-performance/">http://www.androidsoftwaredeveloper.com/2010/02/25/sqlite-performance/

我的建议是分裂您的查询。装载在屏幕上可见的列表项的唯一编号。当用户滚动加载下一组。非常喜欢的Gmail和市场应用。不幸的是我没有一个例子方便:(

这不回答你的问题,但希望它提供了一些启示:)

i am using a custom CursorAdapter to get data from a SQLite database and show it in a listview. The database contains a 2 columns with about 8.000 rows. so i am looking for a way to query and show all the data as fast as possible. i have done this with asyncTask here is the code:

private class PrepareAdapter extends AsyncTask<Void,Void,CustomCursorAdapter > {

 @Override
 protected void onPreExecute() {
     dialog.setMessage("Wait");
     dialog.setIndeterminate(true);
     dialog.setCancelable(false);
     dialog.show();


     Log.e("TAG","Posle nov mAdapter");
 }

 @Override
 protected CustomCursorAdapter doInBackground(Void... unused) {

   Cursor cursor =  myDbNamesHelper.getCursorQueryWithAllTheData();
   mAdapter.changeCursor(cursor);
   startManagingCursor(cursor);
   Log.e("TIME","posle start managing Cursor" + String.valueOf(SystemClock.elapsedRealtime()-testTime)+ " ms");
     testTime=SystemClock.elapsedRealtime();

     mAdapter.initIndexer(cursor);
     return mAdapter;
 }

 protected void onPostExecute(CustomCursorAdapter result) {

     TabFirstView.this.getListView().setAdapter(result);
     Log.e("TIME","posle adapterSet" + String.valueOf(SystemClock.elapsedRealtime()-testTime)+ " ms");
    testTime=SystemClock.elapsedRealtime();
     dialog.dismiss();
 }

}

this works good except the part when i need to set the result into an adapter. i have done some time tests and it takes aprox 700 ms to make it past the startManagingCursor. the problem is that it takes about 7 seconds to make it past the setAdapter(result) and this is running in UI thread so it makes my app unresponsive (the progress dialog freezes and sometimes does the app). how do i make this time less? can i make this also run in background or any way to increase responsiveness?

tnx.

public class CustomCursorAdapter extends SimpleCursorAdapter implements OnClickListener,SectionIndexer,Filterable,
                                    android.widget.AdapterView.OnItemClickListener{

    private Context context;
    private int layout;
    private AlphabetIndexer alphaIndexer;

    public CustomCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to) {
        super(context, layout, c, from, to);
        this.context = context;
        this.layout = layout;

    }
    public void initIndexer(Cursor c){
         alphaIndexer=new AlphabetIndexer(c, c.getColumnIndex(DataBaseNamesHelper.COLUMN_NAME), " ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {

        Cursor c = getCursor();

        final LayoutInflater inflater = LayoutInflater.from(context);
        View v = inflater.inflate(layout, parent, false);

        int nameCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_NAME);

        String name = c.getString(nameCol);

        /**
         * Next set the name of the entry.
         */
        TextView name_text = (TextView) v.findViewById(R.id.name_entry);
        if (name_text != null) {
            name_text.setText(name);
        }

        int favCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_FAVOURITED);
        int fav = c.getInt(favCol);

        int idCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_ID);

        Button button = (Button) v.findViewById(R.id.Button01);
        button.setOnClickListener(this);
        button.setTag(c.getInt(idCol));
        if(fav==1){
            button.setVisibility(View.INVISIBLE);
        }
        else button.setVisibility(View.VISIBLE);

        return v;
    }

    @Override
    public void bindView(View v, Context context, Cursor c) {

        int nameCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_NAME);

        String name = c.getString(nameCol);

        /**
         * Next set the name of the entry.
         */
        TextView name_text = (TextView) v.findViewById(R.id.name_entry);
        if (name_text != null) {
            name_text.setText(name);
        }
        int favCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_FAVOURITED);
        int fav = c.getInt(favCol);

        Button button = (Button) v.findViewById(R.id.Button01);
        button.setOnClickListener(this);
        int idCol = c.getColumnIndex(DataBaseNamesHelper.COLUMN_ID);
        button.setTag(c.getInt(idCol));
      //  Log.e("fav",String.valueOf(fav));
        if(fav==1){
            button.setVisibility(View.INVISIBLE);
        } else button.setVisibility(View.VISIBLE);
    }



    @Override
    public int getPositionForSection(int section) {
        return alphaIndexer.getPositionForSection(section);
    }

    @Override
    public int getSectionForPosition(int position) {
          return alphaIndexer.getSectionForPosition(position);
    }

    @Override
    public Object[] getSections() {
          return alphaIndexer.getSections();
    }
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        Log.e("item Click", arg1.toString()+ " position> " +arg2);
    }

    @Override
    public void onClick(View v) {
            if(v.getId()==R.id.Button01){
                //Log.e("Button Click", v.toString()+ " position> " +v.getTag().toString());
                v.setVisibility(View.INVISIBLE);
                DataBaseNamesHelper dbNames = new DataBaseNamesHelper(context);
                dbNames.setFavouritesFlag(v.getTag().toString());
            }

        }



}

解决方案

The reason for the slow time in loading the adapter is the internal call the CursorAdapter makes to Cursor.getCount().

Cursors in Android are lazily loaded. The results are not loaded until they are needed. When the CursorAdapter calls getCount() this forces the query to be fully executed and the results counted.

Below are a couple links discussing this very issue.

http://groups.google.com/group/android-developers/browse_thread/thread/c1346ec6e2310c0c

http://www.androidsoftwaredeveloper.com/2010/02/25/sqlite-performance/

My suggestion would be to split up your query. Load only the number of visible list items on screen. As the user scrolls load the next set. Very much like the GMail and Market applications. Unfortunately I don't have an example handy :(

This doesn't answer your question but hopefully it provides some insight :)

这篇关于使用游标带的ListView适配器大量数据的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆