2013-04-20 69 views
2

我正在處理一個應用程序中的性能問題。也許你們中的一個能幫助我?Android SQLite快速獲取光標的所有數據

我有一個大約10K條目的數據庫。 我使用SQLiteDatabase-類的默認查詢方法查詢元素。 查詢本身速度不夠快。

查詢完成後,我必須在谷歌地圖上顯示結果。 爲此,我從包含標記信息的光標生成結果數組。

我使用的方法看起來有點像這樣:

final ArrayList<MarkerElement> result = new ArrayList<MarkerElement>(); 
    cursor.moveToFirst(); 
    while (!cursor.isAfterLast()) { 
     result.add(new MarkerElement(
       cursor.getString(COL_TITLE), 
       cursor.getString(COL_SNIPPET), 
       new LatLng(
         cursor.getDouble(COL_LAT), 
         cursor.getDouble(COL_LNG)), 
       cursor.getString(COL_OTHER_USEFUL_DATA)); 
     cursor.moveToNext(); 
    } 
    cursor.close(); 

MarkerElement只是包含所需的值在谷歌地圖標記的類。

現在的問題是,循環遍歷所有遊標元素需要很長時間。 另外我想不出一個聰明的方式來延遲加載像ListView中的結果,因爲我需要同時顯示所有結果。

有什麼我可以做的,以顯着加快這個過程?

任何幫助,非常感謝!

問候

回答

5

我不太確定查詢是真的一樣快,您認爲它是。很可能實際查詢只能用cursor.moveToFirst()語句執行,而不能在調用query()或rawQuery()(或其他任何查詢方法)時執行。

無論如何,查詢應該足夠快,以保持用戶很快就能等待。如果不是,那麼你可能要考慮使用SELECT * FROM your_table LIMIT START,COUNT(例如,SELECT * FROM your_table LIMIT 0,1000檢索前1000行)以塊的形式加載它。

該查詢不能在UI線程上發生,因此您希望在AsyncTaskLoader或更好的CursorLoader中運行該查詢。沒有ContentProvider的CursorLoader是可能的,你可以在這裏看到:https://stackoverflow.com/a/7422343/534471

假設您需要爲每條1000條記錄運行10個查詢,那麼您將擁有10個可以使用LoaderManager管理的CursorLoaders。 LoaderManager管理遊標(打開和關閉它們),在方向更改中保留遊標並在後臺任務中運行所有內容,因此不會阻塞ui線程。如果內容發生更改,LoaderManager也會重新查詢數據庫(請參閱:https://stackoverflow.com/a/5603959/534471)。 當LoaderManager通知您的片段或您的活動光標已完成加載時,它會調用onLoadFinished()(請參閱:http://developer.android.com/reference/android/support/v4/app/LoaderManager.LoaderCallbacks.html)。

什麼減慢你的代碼不僅僅是查詢數據庫,還創建10'000 MarkerElement和另外10'000 LatLng對象。我不知道你的要求,但如果你看到任何沒有這些對象的機會,肯定會加快你的代碼。消除MarkerElements/LatLng的另一個理想效果是內存使用率。對於針對手機的應用,具有3個字符串和2個Double的20'000個對象相當可觀。

使用CursorLoaders和LoaderManager將允許您從光標檢索值並直接填充您的UI視圖,而無需MarkerElements和LatLng。它也可以讓你加載懶惰。每當爲其中一個CursorLoaders調用onLoadFinished()時,您可以填充視圖(在ui線程上調用onLoadFinished(),除非從非ui線程調用initLoader/restartLoader)。如果1000個視圖太多而無法一次填充,請將查詢分解爲較小的部分或添加一種機制,以10或100(對於每個遊標)爲單位填充視圖。

如果您需要當前存儲在MarkerElement中的信息,例如當用戶選擇其中一個標記時,在視圖上使用setTag(),該視圖顯示標記以存儲數據庫記錄的主鍵。使用該鍵可以從數據庫中檢索記錄,甚至可以從已經查詢過的光標(即需要一些映射機制,但它是可行的)中獲得更好的記錄。

摘要:

  • 將查詢分爲幾個子查詢來獲取較小的數據集
  • 使用CursorLoaders和CursorManager會來管理不同的查詢/光標
  • 不要創建MarkerElement和LatLng每行但直接從返回的遊標填充視圖
  • 可能在幾個步驟中填充每個遊標以保持UI響應
  • 使用視圖上的setTag()可以檢索視圖後面的數據