2012年9月26日 星期三

[AndroidDev] New resources selector (>= API 3.2)

Screen density dpi (dots per inch)
ex: 相同 physical area "low" density 會比 a "low" density screen "normal" or "high" density screen 較少 pixel。

dp (density-independent pixel)
  • The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen
  • The baseline density assumed by the system for a "medium" density screen (160 dpi).
  • px = dp * (dpi / 160)
    • ex: on a 240 dpi screen, 1 dp equals 1.5 physical pixels.
  • scaling ratio
    • 3(ldpi) : 4(mdpi) : 6(hdpi) : 8(xhpi)
    • ex: 480 x 800 hdpi/1.5 -> 320 x 533 mdpi in dp's

Screen size
  • Supported from 1.6.
  • 是系統依照 pixel and density 去算出長寬的 dp 然後對應所得。
  • Resolustion convert to dp presentaion of mdpi and decide its size (small, ..)。
  • 分類:
    • xlarge screens are at least 960dp x 720dp. (>= 2.3)
      • approximately-10” tablets, ex: Motorola Xoom
    • large screens are at least 640dp x 480dp.
      • ex: Dell Streak and original 7” Samsung Galaxy Tab
    • normal screens are at least 470dp x 320dp.
    • small screens are at least 426dp x 320dp.
      • Android does not currently support screens smaller than this.
  • 將裝置 dpi 轉至 mdpi,對應上表,長寬最接近且不小於標準之分類。ex:
    • A QVGA screen is 320x240 ldpi.
      • ldpi * 4/3 = mdpi
      • Result: 426dp x 320dp => small
    • The Xoom is a typical 10” tablet with a 1280 x 800 mdpi screen.
      • Result: 1280 x 800 => xlarge
    • The Dell Streak is a 800 x 480 mdpi screen.
      • Result: 800 x 480 => large
    • A typical 7” tablet has a 1024 x 600 mdpi screen.
      • Result: 1024 x 600 => large
      • But!! Exception "Samsung Galaxy Tab"
      • Samsung Galaxy Tab 1024 x 600 7” 應該是為 large,但因為 device configure 視為 hdpi 所以 hdpi * 2/3 = mdpi => 682dp x 400dp => normal!! 所以它應該是 large 但系統會將其視為 normal。
      • This was a mistake in the framework’s computation of the size for that device that we made. Today no devices should ship like this....

新增於 3.2 的屬性:
  • width dp
    • 現在螢幕方向的寬(dp),也就是當方向改變,寬也會隨之改變。
    • the current width available for application layout in “dp” units; changes when the screen switches orientation between landscape and portrait.
  • height dp
    • 現在螢幕方向的高(dp),也就是當方向改變,寬也會隨之改變。
    • the current height available for application layout in “dp” units; also changes when the screen switches orientation.
  • smallest width dp
    • 螢幕高與寬的最小值,此值固定,不會因為螢幕方向改變而改變。
    • the smallest width available for application layout in “dp” units; this is the smallest width dp that you will ever encounter in any rotation of the display.

Typical numbers for screen width dp are:
  • 320
    • a phone screen 
    • 240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi, etc
  • 480
    • a tweener tablet like the Streak 480 x 800 mdpi
  • 600
    • a 7” tablet 
    • 600 x 1024
  • 720
    • a 10” tablet
    • 720 x 1280, 800 x 1280, etc


Resources Selector Examples

限定使用資源的最小寬度(smallest-width),如下:
res/layout/main_activity.xml           # For phones
res/layout-sw600dp/main_activity.xml   # For 7” tablets
res/layout-sw720dp/main_activity.xml   # For 10” tablets
Android 會選擇最接近但不大於的自身寬度的資源,如 700dp x 1200dp tablet 會使用 layout-sw600dp 裡的資源。


限定使用資源的寬度(width),假設你想直向時只顯示某區塊,而橫向時因為寬度較大,想顯示多點內容,可以使用這方式,如下:
res/layout/main_activity.xml          # Single-pane
res/layout-w600dp/main_activity.xml   # Multi-pane when enough width

smallest width < 600 時使用 layout; 大於 600 則會依據方向所在的寬使用 layout-sw600dp 或 layout-sw600dp-w720dp:
res/layout/main_activity.xml                 # For phones

res/layout-sw600dp/main_activity.xml         # Tablets

res/layout-sw600dp-w720dp/main_activity.xml  # Large width



// 或是寫成 layout-sw600dp-port,表示直向時使用此

res/layout/main_activity.xml                 # For phones

res/layout-sw600dp/main_activity.xml         # Tablets

res/layout-sw600dp-port/main_activity.xml    # Tablets when portrait


和舊的 qualifier 一同使用,如下:
// 使用 layout-swNNNdp 比 layout-port 好
res/layout/main_activity.xml                 # For phones
res/layout-land/main_activity.xml            # For phones when landscape
res/layout-sw600dp/main_activity.xml         # Tablets


相容性寫法

Type 1 - Using new qualifiers with old qualifiers
new qualifiers(ex: layout-sw600dp) 會被舊版本忽略,所以以下寫法能 work:
res/layout/main_activity.xml           # For phones
res/layout-xlarge/main_activity.xml    # For pre-3.2 tablets
res/layout-sw600dp/main_activity.xml   # For 3.2 and up tablets

Type 2 - Using new qualifiers with old qualifiers for different layouts
利用 values selector 使用相同名稱指向不同 layout:

res/layout/main_activity.xml           # For phones
res/layout/main_activity_tablet.xml    # For tablets


res/values-xlarge/layout.xml
res/values-sw600dp/layout.xml

res/values-sw600dp/layout.xml:

    
            @layout/main_activity_tablet
    


Type 3 - Select in code
在程式中判斷螢幕大小決定 layout:
public class MyActivity extends Activity {
    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate();

        Configuration config = getResources().getConfiguration();
        // config.smallestScreenWidthDp: >= API 3.2
        if (config.smallestScreenWidthDp >= 600) {
            setContentView(R.layout.main_activity_tablet);
        } else {
            setContentView(R.layout.main_activity);
        }
    }
}


* Reference
- Android Developers Blog: New Tools For Managing Screen Sizes
- Supporting Multiple Screens

2012年9月15日 星期六

[Screen] Sensor-on-lens

Sensor-on-lens
  • 傳統螢幕
    • 由三層組成,最底層是顯示層 (Display),中間是感應層 (Sensor),而最上是鏡片層 (Len)。
    • 這三層就組成了觸控屏幕,既可顯示影像,亦可感應手指觸控。
  • 而 Sensor-on-lens 就是將感應器整合在鏡片內,螢幕就由兩層所組成。
  • 優點
    • 可讓螢幕變得更薄。
    • 提升了畫面的清晰度。
    • 在光線下影像會較明亮。
    • user 使用起來會更覺 “貼手”。


* Reference
- Sony Mobile

[JavaScript] Regular Expression syntax

RegExp(pattern [, flags])
/pattern/flags

  • pattern
    • The text of the regular expression.
  • flags
    • If specified, flags can have any combination of the following values:
  • g
    • global match
    • 找全部。因為 REGEX 預設碰到第一個符合的內容就結束比對。
  • i
    • ignore case 勿略大小寫。
  • m
    • Treat beginning and end characters (^ and $) as working over multiple lines (i.e., match the beginning or end of each line (delimited by \n or \r), not only the very beginning or end of the whole input string)


* Reference
- RegExp | MDN
石頭閒語:Regular Expression (RegExp) in JavaScript - 樂多日誌

[Android] Memory Cache

Reference
  • reference 的可以分為多種強度,我們最熟悉和最常使用的是 strong reference。
  • Four different degrees of reference strength: strong, soft, weak, and phantom.
  • 強度的差異在於 reference 和 garbage collector 間的互相影響關係。

Strong Reference
// buffer 就是 strong reference
StringBuffer buffer = new StringBuffer();
  • 當 reference 指向一個以上的物件,便是 strong reference。
  • 可以防止此 reference 被 GC。
  • 缺點:
    • Memory: 因為使得物件不能被回收,所以有造成 memory leak 的危險。
    • Caching: 假設在 application 中應用到許多大圖片,為了一直 reload 而 cache 圖片,所以 always 會有 reference 指向圖片,使得它在 memory 且不會被回收,也就是說我們得決定它是否該被移除且使其可以回收。

WeakReference
weak reference 則是隨時有可能已被回收。
// API 使用方式如下,建立 Widget 的 WeakReference。
WeakReference weakWidget = new WeakReference<widget>(widget);
// 取出 Widget object。
// 注意: 因為物件可以被回收,所以可能會得到 null。
weakWidget.get()
WeakHashMap
  • 作用類似 HashMap,只是 key 是使用 weak reference,若 key 變成 garbage 則它的 entry 便自動會被移除。
  • 但並不是你啥也也沒做他就能自動釋放,而是你使用到 value 才會被釋放。
  • super(key, queue); 只有 key 才是 weak reference,value 仍是 strong reference,所以 System.gc() 後,key 會被清除,value 則是才被視為 weak reference 然後到被調用到了才會被清除。

Reference queues
  • 當 WeakReference 回傳 null 時表示指向的物件已被回收,WeakReference object 也無用了,所以如 WeakHashMap 會去移除這類的 WeakReference object,避免 WeakHashMap 一直成長,其中卻有很多無用的 WeakReference 。
  • ReferenceQueue 可以幫助你管理這些 dead reference。
    • 如果你將 ReferenceQueue 傳入 weak reference's constructor,當有 reference 指向的物件被回收時,該 reference 會自動被 insert 到 ReferenceQueue 中,所以你可以定期清裡 ReferenceQueue 也就會清理了 dead reference。

Soft references
  • 類似於 weak reference,差異是比 weak reference 不易被回收。
  • 因為 soft reference 會盡量被保留在 memory 所以適合做 image cache。

Phantom References
  • Its get() method always returns null.
  • 用處:
    • 可以讓你決定何時將物件從 memory 移除。ex: manipulating large images,你可以先確定現在這一張已被移除,再載入下一張以避免 OOM。
    • 避免 finalize() method 可以 "resurrect" 建立了 strong reference 的 object。
      • override finalize() 的物件至少要被視為 GC 對象兩次以上才能被回收到,而不能及時的被回收,也因此會有多個待回收的 garbage 存在著等著被回收。

Android itself employs some caching as part of the resources infrastructure, so you are already getting the benefit of memory caching.

使用 bitmap 時,記得使用 recycle(),可以幫助釋放空間,所以若是再呼叫 getPixels() or setPixels(),可能會得到 exception,所以建議當不會再使用到 bitmap 時再使用。

LruCache
  • API level 12 (3.1)
  • Support Library back to API level 4 (1.6).
  • 管理與 cache 物件,呼叫 get(key) 取出物件,若物件不存在則會呼叫 create() 產生物件,並將新產生的物件加入 head of cache 再將其回傳。
  • 加入新物件時,cache 會檢查是否超過指定的大小,若超過則會刪除最後一筆 (tail of cache list)。

// override 這個 method 可以讓我們決定 cache 中每個物件 size 怎麼計算,default returns 1。
@Override
protected int sizeOf( String key, Bitmap value )
{
    return value.getByteCount();
}

Note:
Bitmap#getByteCount()
  • Supported from API Level 12。
// 建構子中則傳入想預設此 cache 的大小,這裡設定最大為 5 M。
// 所以一旦超過 5 M,物件會從最後一直被移除直到總大小小於 5 M。
public LruMemoryCache(Context context)
{
    super( 5 * 1024 * 1024 );
    this.context = context;
}

為避免發生 OutOfMemoryError,在系統呼叫 onLowMemory() 時建議呼叫 LruCache#evictAll() 移除所有元素再重建。

Note:
  • onLowMemory() 會被呼叫是因為整個系統的空間不足而不是因為你的 App 所用的空間已不足!
    • 所以等到此 method 被呼叫時已來不及,更好的方式是在 App 執行一開始便設定適當的大小限制給它。
    • ActivityManager#getMemoryClass() (API Level 5) 可以取得該 application 在 該 device 中的分配空間:
      • 單位為 megabytes。
      • 預設為 16 M,空間大點裝置可到 24 或更高。

也可以利用 LruCache 來管理在 SD card 中的檔案大小:
  • 儲存 File object 在 LruCache(override create())。
  • 以 file.length() 計算檔案大小 (override sizeOf())。
  • 移除物件時刪除 SD card 中的檔案 (override entryRemoved())。


* Reference
- Understanding Weak References | Java.net
- Styling Android » Blog Archive » Memory Cache – Part 1
- Styling Android » Blog Archive » Memory Cache – Part 2
- Styling Android » Blog Archive » Memory Cache – Part 3
- Styling Android » Blog Archive » Memory Cache – Part 4
- WeakHashMap的神话 - - ITeye技术网站
- WeakHashMap是如何清除不用的key的