2011-05-14 3 views
0

ListView을 사용하여 시각화하려는 수천 개의 행을 반환하는 SQLite 쿼리가 있습니다.안드로이드 - SQL 커서를 기반으로 한 매우 큰 ListView 만들기

UI 스레드의 응답을 유지하기 위해 백그라운드 스레드에 ListAdapter을 만듭니다.

그러나 대부분의 시간이 걸리고 (ANR이 발생할 수 있음) 진술은 ListActivity.setListAdapter이며 UI 스레드에서 실행해야합니다.

 
public class CursorTestActivity extends ListActivity { 

    private static final String LOGTAG = "DBTEST"; 

    private DatabaseManager mDbManager; 
    private Cursor mCursor; 
    private HandlerThread mIOWorkerThread; 
    private Handler mIOHandler; 
    private Handler mUIHandler; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     mDbManager = new DatabaseManager(this); 

     mUIHandler = new Handler(); 
     createIOWorkerThread(); 

     log("creating cursor"); 
     mCursor = mDbManager.getCursor(); // does db.query(...) 
     startManagingCursor(mCursor); 

     mIOHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       setMyListAdapter(); 
      } 
     }); 
     log("onCreate done"); 
    } 

    private void setMyListAdapter() { 
     log("constructing adapter"); 
     // CustomCursorAdapter implements bindView and newView 
     final CustomCursorAdapter listAdapter = new CustomCursorAdapter(this, 
       mCursor, false); 
     log("finished constructing adapter"); 
     mUIHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       log("setting list adapter"); 
       setListAdapter(listAdapter); // gets slower the more rows are returned 
       log("setting content view"); 
       setContentView(R.layout.main); 
       log("done setting content view"); 
      } 
     }); 
    } 

    private void createIOWorkerThread() { 
     mIOWorkerThread = new HandlerThread("io_thread"); 
     mIOWorkerThread.start(); 
     Looper looper = mIOWorkerThread.getLooper(); 
     mIOHandler = new Handler(looper); 
    } 

    private void destroyIOWorkerThread() { 
     if (mIOWorkerThread == null) 
      return; 
     Looper looper = mIOWorkerThread.getLooper(); 
     if (looper != null) { 
      looper.quit(); 
     } 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     if (mDbManager != null) 
      mDbManager.close(); 
     destroyIOWorkerThread(); 
    } 

    private static void log(String s) { 
     Log.d(LOGTAG, s); 
    } 

} 

답변

0

커서가 지연로드되어 있으므로 커서가 처음로드 될 때 커서가로드됩니다. getCount는 이러한 액세스입니다. setAdapter 메소드가 커서에서 getCount를 호출합니다. 성능 문제가 있습니다.

  • 어댑터에 빈 커서를 설정하고 커서를로드하는 동안 빈 목록을 표시 할 수 있습니다. 그런 다음 어댑터에서 changeCursor 메소드를 사용하여 커서를 새 것으로 변경하십시오.
  • 첫 번째 쿼리에서 예를 들어 100 개의 행을 가져온 다음 백그라운드에서 행을 더로드하고 changeCursor를 새 행으로로드 할 수 있습니다.
  • 또는 getCount 자체 구현이있는 Cursor 자체 구현을 생성하고 요청시 요청 된 행을 반입 할 수 있습니다.