2015/08/18

Store and retrieve a class object in SharedPreferences

之前在 Save ArrayList to SharedPreferences 提到過,如何將 ArrayList 物件存到 SharedPreferences 裡,最近看到一個更棒的方式,那就是使用 Gson

假設我現在有個 MyObject 物件想要存起來,可以這樣寫:

要取出來時:

回到之前 ArrayList 的問題,儲存可以改用上面範例來處理,至於取出的方法需要改寫成這樣:

比起原本的程式碼,變得乾淨俐落許多!

Reference:
http://stackoverflow.com/questions/5418160

2015/04/28

Test Your Deep Links

今天看文件才想到 adb 有提供指令可以直接發 Intent 給 App,而且還能帶 URI data,這樣要用來測試 protocol 就方便多了!

Reference:
https://developer.android.com/training/app-indexing/deep-linking.html#testing-filters

2015/04/27

android.database.CursorWindowAllocationException

當 Cursor 沒有確實關閉並且累積到一定數目時,App 就會出現異常報錯,無法查詢資料庫,甚至 crash。這邊記錄一些容易出錯的例子:

。提前返回
    有時會沒注意到在調用 close() 之前就 return 了,尤其在比較複雜的程式碼中就可能會疏忽。

。異常處理
    在還沒執行 close() 之前就因為處理 exception 而跳過。

要避免這種情形,應該要把 close() 放到 finally 裡確保它會執行。

另外我們也可以在 Cursor 的建構及關閉時加上 log 來測試及偵錯。

這樣就能清楚檢查是否有 Cursor 未確實關閉,但要先等 App 完全結束程序時再做,因為有些 Cursor 可能仍在背景運行中。

Reference:
http://oteku.blogspot.tw/2013/11/how-to-detect-android-cursor-leak-en.html

2015/04/26

java.util.ConcurrentModificationException

前陣子在做 for-each 執行某項過濾功能時遇到這個異常報錯,原因在於 for-each 的架構是不能使用於過濾需求的,一旦變動了集合的內容便會發生錯誤。在這邊可以使用 Iterator 調動集合的方式來解決,在多個執行緒中也能做到同步。

另外如果集合不大,也可以使用 counted loop 來處理。

Reference:
http://stackoverflow.com/a/223929/1770125

2015/03/01

POJO

POJO,全名為 Plain Old Java Object。它是一個簡單的 Java Object 概念定義,可以包含邏輯處理,以下三種情況不能稱作 POJO:

1. 繼承 Java frameworks 的 class
2. 實作 Java frameworks 的 interface
3. 包含 Java frameworks 的 annotation
Reference:
http://martinfowler.com/bliki/POJO.html
http://en.wikipedia.org/wiki/Plain_Old_Java_Object

Programmatically Declare Styleable In Custom View

在我們設計 custom View 的時候,一般都會想要定義一些專屬的 attributes 放在 attrs.xml 裡面,方便之後可以調整它的參數來因應 layout 規格。例如在 Chris Banes 的 FloatLabelLayout 中,他先在 attrs.xml 定義了每個方向的 padding,以及要用作 label 的 hint 和 TextAppearance,

然後在 FloatLabelLayout.java 取得外部利用這些 attributes 所設定的數值,進而調整裡面需要變動的元件。

但是有些時候,我們可能想要直接在程式碼中定義這些行為,那該如何實作呢?

在這個例子中,我們先宣告了 styleable 這個 int array,放入需要用到的 attributes,接著調用 Context#obtainStyledAttributes() 傳回一個 TypedArray 的物件,裡面便會包含 reference 到這些 attributes 所設定的數值,再來就可以選擇適當的 method 來取用了。

這邊有幾個需要注意的地方,由於 context.obtainStyledAttributes() 內部設計預設是認定 styleable 中的 attributes 是排序過的,所以他回傳回來的數值是依其在 native 的順序寫入到 TypedArray,若是我們的 styleable 沒 sort 過,就會得到非預期的結果;另外就是從 TypedArray 取值時傳入的是 attribute 在 styleable 的 index,而非 attribute 本身。

Reference:
http://droidux.com/programmatically-declare-styleable-custom-view/

2015/02/16

Avoid float and double if exact answers are required

float 和 double 主要是被設計用作科學及工程運算,若是需要精確結果的商業計算,它們並不適合,原因在於它們不能準確地表達 0.1 或任何 10⁻¹ 的倍數。

假設你口袋有 $1.03,而你花了 42¢,那會剩下多少?
不幸地,它的輸出結果是 0.6100000000000001,這不是唯一的特殊案例;假設你口袋有 $1,你買了 9 個 10¢ 的物品,那會找回多少零錢?
根據這個結果,你會拿回 $0.09999999999999998。

我們可能會覺得只要利用輸出前幾位數做四捨五入來 work around 就可以了,但這招並不是每次都能奏效。再來舉一個例子,假設現在你口袋有 $1,架上擺著糖果,價格依序為 10¢、20¢、30¢,依此類推,如果從第一顆糖果開始買起,你可以買多少顆糖果,並且能找回多少零錢?
當你跑完這段程式碼,你會發現你可以買 3 顆糖果,然後找回 $0.3999999999999999,這結果當然是錯的。要解決這個情況,我們必須改用 BigDecimal 來處理商業計算。
這次我們得到了正確的答案,你可以買 4 顆糖果,找回 $0.00。

不過,使用 BigDecimal 也有缺點,它寫起來不是很方便,而且格式也麻煩,不容易 review。另外一個方法就是視情況使用 int 或 long 來代換,像是在這個例子中,因為數值不大,我們可以把單位都改用分來計算。
Reference:
http://stackoverflow.com/questions/5257166
Effective Java》Item 48