今天看文件才想到 adb 有提供指令可以直接發 Intent 給 App,而且還能帶 URI data,這樣要用來測試 protocol 就方便多了!
Reference:
https://developer.android.com/training/app-indexing/deep-linking.html#testing-filters
2015/04/28
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
。提前返回
有時會沒注意到在調用 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
另外如果集合不大,也可以使用 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
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/
然後在 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
假設你口袋有 $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
2015/01/21
Context, What Context?
我們在開發 Android app 時,最常用到的元件非 Context 莫屬了,但它也最有可能會被誤用。假設現在定義了一個 singleton,需要傳入 Context 來做後續如載入 resources 之類的工作,並且會將這個 reference 存下來。
這時會造成一個問題,我們不知道這個 Context 的來源是什麼,而如果來源是 Activity 或 Service,那我們扣著這個 reference 也是不安全的。原因在於為了維持這個 static reference,那與它相關聯的所有物件就不會被回收,如果這個 Context 來源是 Activity,這就意味著連同在這個 Activity 裡面的 View 以及各種物件都會被扣著,增加 memory leak 的風險。為了避免這個情況,我們可以調整 reference 到 Application Context 身上。
這樣我們便不用顧慮 Context 來源是什麼,因為 Application Context 本身就是 singleton,不需要再花資源建另外一個 static reference。
那我們為什麼不乾脆都只 reference 到 Application Context 身上就好了呢?那是因為有些功能不適合由 Application Context 執行,最主要的就是 UI 行為,例如 Layout Inflation,而執行 UI 功能最適合的人選就是 Activity,一般來說這些功能原本也就被設計在 Activity 內運作。
Reference:
http://possiblemobile.com/2013/06/context/
這時會造成一個問題,我們不知道這個 Context 的來源是什麼,而如果來源是 Activity 或 Service,那我們扣著這個 reference 也是不安全的。原因在於為了維持這個 static reference,那與它相關聯的所有物件就不會被回收,如果這個 Context 來源是 Activity,這就意味著連同在這個 Activity 裡面的 View 以及各種物件都會被扣著,增加 memory leak 的風險。為了避免這個情況,我們可以調整 reference 到 Application Context 身上。
這樣我們便不用顧慮 Context 來源是什麼,因為 Application Context 本身就是 singleton,不需要再花資源建另外一個 static reference。
那我們為什麼不乾脆都只 reference 到 Application Context 身上就好了呢?那是因為有些功能不適合由 Application Context 執行,最主要的就是 UI 行為,例如 Layout Inflation,而執行 UI 功能最適合的人選就是 Activity,一般來說這些功能原本也就被設計在 Activity 內運作。
Reference:
http://possiblemobile.com/2013/06/context/
訂閱:
文章 (Atom)