Android自訂Cursor遇到的一個小問題
Android應用很多情況下儲存大量資料都會用SQliter,使用sqlliter不免要和cursor打交道,靈活使用cursor會省很多事。如將自己的資料群組合在一個虛擬表中(資料集合),通過Provider以cursor形式返回給使用者,還可以規定cursor每取一次返回多少記錄,以減少UI資料量大的負載壓力。(如果只是封裝下資料以cursor方式返回,MetrixCursor可以完成此需求,其publicvoid addRow (Object[]columnValues)方法可以幫你維護添加進去的對象數組資料)。
具體實現代碼如下:
final Map data = new HashMap(); data.put(wifi,on); Cursor cursor = new AbstractCursor() { private String[] names; /** * 記錄數 * @return */ @Override public int getCount() { return data.size() > 0 ? 1 : 0; } /** * 擷取每一列的名稱,對於SharedPreferences 就是每一個key * @return */ @Override public String[] getColumnNames() { if(names == null) { names = new String[0]; if (!data.isEmpty()) { names = new String[data.size()]; Set keySet = data.keySet(); names = (String[])keySet.toArray(new String[0]); } } return names; } @Override public String getString(int column) { String key = names[column]; return (String)data.get(key); } @Override public short getShort(int column) { return 0; } @Override public int getInt(int column) { return 0; } @Override public long getLong(int column) { return 0; } @Override public float getFloat(int column) { return 0; } @Override public double getDouble(int column) { return 0; } @Override public boolean isNull(int column) { return false; } };紅色部分是要注意的代碼,開始是這麼寫的:
if(names == null) { names = new String[0]; if (!data.isEmpty()) { names = new String[data.size()]; Set keySet = data.keySet(); int i = 0; for (String key : keySet) { names[i++] = key; } } }但是Set有提供的轉成Array的方法toArray(),於是改成了
names = (String[])keySet.toArray();
但是結果是錯誤的,打斷點跟蹤後發現cursor中是有資料的,但是如果取得花是會出錯的。
對於Set而言,它只知道它內部儲存的是Object,所以預設情況下,toArray只能是返回一個由這些Object構成的Object數組出來。
但程式的作者或許更清楚其內部元素的更具體的類型,因此,Set類提供了toArray的另一個重載版本,允許使用者指定一種比Object[]更具體的數群組類型,方法是傳遞一個使用者想要的數群組類型的一個數組執行個體進去,多長都無所謂(因此我們常常使用一個0長度的,畢竟把類型帶進去就OK了),於是,toArray內部就會按照你想要的這種類型,給構造一個數組出來。這樣構造出來的數組,當然是很安全地被調用者轉換回那個實際的類型。