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

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

问题描述

我使用自定义CursorAdapter从SQLite数据库获取数据并在列表视图中显示它。数据库包含2列,约有8.000行。所以我正在寻找一种方法来查询和显示所有的数据尽可能快。我这样做asyncTask这里是代码:

  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();
}

}



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



tnx。

  public class CustomCursorAdapter extends SimpleCursorAdapter实现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);
查看v = inflater.inflate(layout,parent,false);

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

String name = c.getString(nameCol);

/ **
*接下来设置条目的名称。
* /
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)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);

/ **
*接下来设置条目的名称。
* /
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)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());
}

}



}


解决方案

加载适配器的慢时间的原因是CursorAdapter对Cursor.getCount()的内部调用。



Android中的游标是懒惰加载的。在需要之前,不会加载结果。当CursorAdapter调用getCount()时,这将强制完全执行查询并计算结果。



以下是讨论这个问题的几个链接。



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

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



我的建议是拆分查询。仅加载屏幕上可见列表项的数量。当用户滚动加载下一组。非常喜欢GMail和Market应用程序。不幸的是我没有一个例子:(



这不能回答你的问题,但希望它提供了一些洞察力:)


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天全站免登陆