2010-03-30 23 views
33

我通常傾向於定義使用POJO的,如文章,評論等POJO的與光標在Android中

我正要實現我的列表視圖之一的適配器的AlphabetIndexer我的應用程序的模型層。現在這個適配器接受一個文章集合,我通常從我的包裝器獲得一個SQLiteDatabase。

的AlphabetIndexer建築工的簽名如下:

public AlphabetIndexer (Cursor cursor, int sortedColumnIndex, CharSequence alphabet) 

因爲這個不接受集合或類似的東西,只是一個指針,它讓我想:也許我不應該創建對象對於我的模型,只需使用從數據庫返回的遊標?

所以問題是,我猜我應該怎麼做,用POJO的Collections來表示數據,還是隻在我的應用程序中使用Cursors?

任何輸入?

+0

你想使用由一個lib提供的遊標的美好的事物?請參閱:http://stackoverflow.com/questions/4285398/would-you-like-to-integrate-a-pojo-or-cursor-based-library-in-your-android-app – OneWorld 2010-11-26 13:00:05

+0

我正在做類似的事情在這裏http://stackoverflow.com/questions/10224233/alphabetindexer-with-custom-adapter-managed-by-loadermanager – toobsco42 2012-04-26 06:21:19

回答

13

我遇到過類似的問題。現在,我正在遠離POJO。但請注意,如果您願意,您可以爲POJO集合創建自己的Cursor界面。

+1

我知道這一點,但它似乎有點循環...創建一個集合的光標爲創建光標。 :) – benvd 2010-03-30 13:37:46

+1

哦,沒問題。這就是我放棄POJO並將其放在「遊標」中的原因之一。用MVC術語來說,你可以用愚蠢的模型和智能控制器來解決問題。 – CommonsWare 2010-03-30 13:51:56

+4

我決定接受這個答案,因爲我現在使用這種方法。具體來說,我在我的'SQLiteOpenHelper'中爲每個表創建了一個公共內部類。這些類包含一堆方法,以防止我不得不混淆列名或數字。性能差異在'ListViews'中立即顯而易見,只需幾十個條目。另外,我似乎更喜歡'CursorAdapters'到'BaseAdapters'。 我從你的書中獲得了靈感(特別是Android教程2.9中的第102頁),當我問這個問題時我沒有回來,所以謝謝! :-) – benvd 2010-07-27 14:52:08

9

實體對象(PO​​JO)一票投票。傳遞遊標,特別是UI層,對我來說感覺非常錯誤(不管Android sdk有沒有暗示這樣做)。通常有幾種方式來填充你的UI,我傾向於避免那些直接使用遊標的方法。例如,要填充我的自定義列表視圖,我使用SimpleAdapter併爲我的集合對象賦予它們自己的表示形式,作爲SimpleAdapter構造函數的List<? extends Map<String, ?>>

我使用了一個模式,其中每個表由一個實體對象包裝,並有一個提供程序類來處理與該實體相關的CRUD操作。可選地,如果我需要集合的擴展功能,我也包裝它們(即,EntityItems extends ArrayList<EntityItem>)提供者有一個基類,我傳遞一個引用到DbAdapter類的引用,該引用在db上執行繁重的工作。

的最大原因,除了個人喜好等,是我想隱藏這種代碼儘可能地遠離我的UI地:

String something = cursor.getString(cursor.getColumnIndex(COLUMN_NAME_CONSTANT)); 

如果我看到那種代碼內嵌在UI層,我通常希望看到更糟糕的潛伏在拐角處。也許我剛剛在大團隊中工作的企業界花費了太多時間,但除非有合理的性能問題,否則我更喜歡可讀性,或者如果這是一項足夠小的任務,表現力只是企業的過度殺手。

+4

「我使用SimpleAdapter併爲我的集合對象賦予它們自己的一個表示形式,使其成爲List <?extends Map >用於SimpleAdapter的構造函數」 - 這涉及大量數據複製,咀嚼CPU時間併產生垃圾。對於任何給定的應用來說,這可能也可能不重要。 – CommonsWare 2010-03-30 14:53:28

+0

我一直密切關注這類事情,並且緩存了這類調用的結果,所以我幾乎不認爲使用這樣的便利函數會導致大量內存或cpu性能下降。這帶來了問題,也許你可以回答。如果我填充一個HashMap並且所有的鍵都是初始化的字符串變量,並且所有的值都是初始化對象的字符串屬性,通過調用map.put(key,value)不是我只是傳遞指針而不是創建一大堆新的對象(垃圾)?我會這樣認爲的,因爲我不太瞭解Java爲自己回答這個問題。 – Rich 2010-03-30 15:35:38

+2

Hey Rich。我也喜歡讓UI不可知的數據來源,UI中的遊標代碼對我來說也很難看,但我可以找到幾個爲什麼需要它們的原因。首先,它們是將數據鏈接到ListViews等最有效的方式。其次,爲了轉換爲集合,你必須線性迭代你的光標,O(n),每行創建一個對象,你不會在光標處,GC將不得不在某個時刻收集這些對象,但最重要的是,你正在將你的整個集合加載到內存中。遊標只保存當前行。 – palako 2010-10-14 03:53:54

12

我喜歡創建遊標支持的POJO類。 A光標支持POJO類有一個構造函數一個光標,並提供以下好處:

  • - 易於使用,返回正確的內容類型干將,更好 比獲得指標,並具有記憶數據的類型在 數據庫中
  • Getter方法可以計算其他getter的結果,就像OO編程應該如何進行一樣
  • Getter返回值可以是枚舉!

這幾個好處是值得的一些樣板代碼,許多許多錯誤已被避免,現在用戶工程師不訪問遊標列本身。我們仍然使用CursorAdapter類,但bindView方法的第一行是從Cursor創建Cursor支持的POJO,從此代碼很漂亮。

下面是一個示例實現,對於用戶工程師來說,將一個不透明的光標變成明確定義的User對象是很簡單的事情,從這點開始,它可以像常規POJO一樣傳遞和訪問,只要後備光標未關閉。 SmartUserCursor是我寫的一個特殊類,用於確保在訪問遊標之前記住並恢復遊標位置,並且它還存儲遊標列索引,因此查找速度很快。

例:

public class User { 

    private final SmartUserCursor mCursor; 

    public User(SmartUserCursor cursor, int position) { 
     mCursor = new SmartUserCursor(cursor, position); 
    } 

    public long getUserId() { 
     return mCursor.getLong(SmartUserCursor.Columns.userId); 
    } 

    public UserType getType() { 
     return UserType.valueOf(mCursor.getString(SmartUserCursor.Columns.type)); 
    } 

    public String getFirstName() { 
     return mCursor.getString(SmartUserCursor.Columns.firstName); 
    } 

    public String getLastName() { 
     return mCursor.getString(SmartUserCursor.Columns.lastName); 
    } 

    public final String getFullName() { 
     return getFirstName() + " " + getLastName(); 
    } 

    public static User newUserFromAdapter(BaseAdapter adapter, int position) { 
     return new User((SmartUserCursor)adapter.getItem(position), position); 
    } 

    public static User newUserBlocking(Context context, long UserId) { 
     Cursor cursor = context.getContentResolver().query(
       Users.CONTENT_URI_CLIENT, 
       Users.DEFAULT_USER_PROJECTION, 
       Users.Columns.USER_ID+"=?", 
       new String[] {String.valueOf(UserId)}, 
       null 
     ); 

     if (cursor == null || !cursor.moveToFirst()) { 
      throw new RuntimeException("No User with id " + UserId + " exists"); 
     } 

     return new User(new SmartUserCursor(cursor, Users.DEFAULT_USER_PROJECTION), -1); 
    } 

    public final void closeBackingCursor() { 
     mCursor.close(); 
    } 

} 
+0

任何示例代碼?也因爲你必須將所有的遊標數據加載到模型對象中,所以速度較慢? – marchinram 2012-07-05 22:18:11

+0

我不加載遊標中的所有數據。我只是有一堆訪問內部遊標的getter。我會在稍後發佈一個例子。 – satur9nine 2012-07-06 02:55:50

+0

很酷的感謝,期待着例子,我目前使用greendao,我認爲做了類似的事情,但會很酷,看到這樣的工作的例子 – marchinram 2012-07-07 17:49:43

2

答案是4歲。 我想現在我們有足夠的CPU能力來擺脫更多的東西。我的想法是隻能使用POJO和ArrayLists;並擴展CursorLoader以將光標映射到背景中的POJO並將數組列表提供給活動;

除非您選擇查詢數百行,但隨後,多久你這樣做,與使用POJO的getter和setter