views:

878

answers:

1

Hi, My ListView (two TextView, one Icon) have more than 4000 rows and It sroll very slowly. The problem is "For{} statement" with "Cursor" make my program worse. I want to get the "First Character"(from one of two TextView) to display when User Scroll. So, any solutions to archive this and make my program better. My function like this:

public void onScroll(AbsListView view, int firstVisibleItem, int VisibleItemCount, int totalItemCount){
 //int lastItem = firstVisibleItem + VisibleItemCount - 1;

 Cursor cursor = mDbHelper.loadTitleRaw();
 startManagingCursor(cursor);

 ArrayList<String> myArrayList = new ArrayList<String>();
 for(cursor.moveToFirst(); cursor.moveToNext(); cursor.isAfterLast()) {
    String mTitleRaw = cursor.getString(cursor.getColumnIndex(SBooksDbAdapter.KEY_TITLE_RAW));
    myArrayList.add(mTitleRaw);
 }
 String[] mString = myArrayList.toArray(new String[myArrayList.size()]);          

 if(mReady){
  char firstLetter = mString[firstVisibleItem].charAt(0);
  if(!mShowing && firstLetter != mPrevLetter){
   mShowing = true;
   mDialogText.setVisibility(View.VISIBLE);
  }
  mDialogText.setText(((Character)firstLetter).toString());
  mHandler.removeCallbacks(mRemoveWindow);
  mHandler.postDelayed(mRemoveWindow, 3000);
  mPrevLetter = firstLetter;
 }
}
+1  A: 

You are almost certainly doing this wrong. You don't want to instantiate a new Cursor on every scroll, you want to create it once, then reuse it. This is usually done in the onCreate() method. You could also get rid of that whole ArrayList / Array mess.

What's happening the way you're doing it is that every time you scroll AT ALL it's querying the database for all the records. Then it's copying all those values into an ArrayList, then it's copying all the values into an array. You're taking one object (with a bunch of data) then turning it into a bunch of objects which each have very little data. Other than being unnecessarily repetitious, this is probably killing you on garbage collection, not to mention running the query over and over. You really only want one copy of the data floating around and you want to make as few queries as possible.

Something like this should help out a lot:

public class MyActivity extends Activity {
    private Cursor cursor;

    public void onCreate(Bundle savedInstanceState) {
        // all the other stuff you're already doing.

        cursor = mDbHelper.loadTitleRaw();
        startManagingCursor(cursor);
    }

    public void onScroll(AbsListView view, int firstVisibleItem, int VisibleItemCount, int totalItemCount) {
         if(mReady){
             cursor.moveToPosition(firstVisibleItem);
             char firstLetter = cursor.getString(cursor.getColumnIndex(SBooksDbAdapter.KEY_TITLE_RAW)).charAt(0);

             if(!mShowing && firstLetter != mPrevLetter){
                 mShowing = true;
                 mDialogText.setVisibility(View.VISIBLE);
             }
             mDialogText.setText(((Character)firstLetter).toString());
             mHandler.removeCallbacks(mRemoveWindow);
             mHandler.postDelayed(mRemoveWindow, 3000);
             mPrevLetter = firstLetter;
         }
    }
}

Bonus points... if the ListView is being populated from a Cursor in the first place (which seems an almost certainty in this case) you might just be able to reuse the same Cursor instead of having 2 floating around.

fiXedd
Hi fiXedd, Thanks for your code! I'll fix this.
Dennie
No problem, hope it helps.
fiXedd