2009-08-26 74 views
2

我一直在處理的這個應用程序有數據庫與多兆字節的數據進行篩選。很多活動只是ListViews在數據庫中通過各種級別的數據遞減,直到我們到達「文檔」,這只是從數據庫中提取並顯示在手機上的HTML。我遇到的問題是,其中一些活動需要能夠通過捕獲鍵擊並在其中重新運行查詢並使用「like%blah%」來搜索數據庫。除非用戶第一次加載數據和用戶首次輸入按鍵時,這種方式可以合理快速地進行。我正在使用ResourceCursorAdapter,我在後臺線程中生成遊標,但爲了做一個listAdapter.changeCursor(),我必須使用Handler將它發佈到主UI線程。然後這個特定的調用會凍結UI線程足夠長的時間帶來可怕的ANR對話框。我很好奇我如何將它完全卸載到後臺線程,以便用戶界面保持響應,並且我們沒有彈出ANR對話框。我最初只是返回一個自定義模型對象的ArrayList並使用ArrayAdapter,但(可以理解)客戶指出這是糟糕的內存管理,而且我對性能不滿意。我真的想避免一個解決方案,我生成對象的龐大名單,然後做一個listAdapter.notifyDataSetChanged /廢棄()Android CursorAdapters,ListViews和後臺線程

這裏是有問題的代碼:

private Runnable filterDrugListRunnable = new Runnable() { 
    public void run() { 
     if (filterLock.tryLock() == false) return; 

     cur = ActivityUtils.getIndexItemCursor(DrugListActivity.this); 

     if (cur == null || forceRefresh == true) { 
      cur = docDb.getItemCursor(selectedIndex.getIndexId(), filter); 
      ActivityUtils.setIndexItemCursor(DrugListActivity.this, cur); 
      forceRefresh = false; 
     } 

     updateHandler.post(new Runnable() { 
      public void run() { 
       listAdapter.changeCursor(cur); 
      } 
     }); 

     filterLock.unlock(); 

     updateHandler.post(hideProgressRunnable); 
     updateHandler.post(updateListRunnable); 
    } 
}; 

回答

1

我發現它很難相信只要listAdapter.changeCursor()會花費足夠的時間來產生ANR,假設您在後臺線程中創建了Cursor。應該不會有那麼多工作需要重新繪製一些列表行。我會仔細檢查一下,看看你在Handler中做的工作是否與你想象的一樣有限。也許可以考慮使用AsyncTask,這樣可以更輕鬆地將後臺工作(doInBackground())與UI上線程後處理(onPostExecute())分開。

您可以嘗試直接替換適配器,方法是再次調用setAdapter(),並將新的Cursor包裝在新的適配器中。

您可以看看AutoCompleteTextView如何處理這種情況,因爲它使用SpinnerAdapter進行動態過濾。也許它的一些技巧可以適用於你的情況。

+0

之前,我添加了changeCursor電話,一切很高興,並在後臺運行。有一次,我添加了這個: updateHandler.post(新的Runnable(){ 公共無效的run(){ listAdapter.changeCursor(現);} }); 一切都變得糟糕。 – MattC 2009-08-27 13:04:48

+0

奇怪的問題:什麼是你的代碼中的filterLock?你是否可能陷入致命的擁抱或僵局? – CommonsWare 2009-08-27 16:42:30

+0

這只是一個鎖,我們曾預料會使用的情況下,用戶在第一個查詢運行時保持打字狀態。 逐步調整CursorAdapter的實際代碼,changeCursor調用notifyDataSetChanged(),這是掛起的位置。 – MattC 2009-08-27 16:49:48