2016年4月20日 星期三

Designtime Layout Attributes

從 Android Studio 0.2.11 開始,為 layout 與元件引進了設計期間(Designtime)的 attributes。
其中兩個 attributes 頗為實用:

tools:text

有時候我們不想要填寫 android:text,卻想要在設計期間看到字串以方便調整 layout 時,就可以使用 tools:text,這樣一來該字串就不會執行期間出現。

tools:listitem

在設計 ListView 的 UI 時,通常只看的到預設的 ListView,看不到自己所設計對應的 ListView Item,此時只要在 ListView 設定 tools:listitem="@layout/view_listview_item" 就可以看到了。

大部分的 android:xxx 的屬性都能搭配 tools:xxx 來使用,例如 tools:visibility 等等。
另外,在使用 tools:xxx 之前,不要忘記宣告了命名空間:
xmlns:tools="http://schemas.android.com/tools"

Ref:
  1. http://tools.android.com/tips/layout-designtime-attributes
  2. http://cloudchen.logdown.com/posts/247618/android-tools-attributes


2016年4月15日 星期五

細說 PriorityQueue

PriorityQueue 的用法在網路上有很多資料可以查詢,這裡就不在介紹,
想在這裡說明的是 PriorityQueue 的實作以及要小心避免的錯誤使用方式。
PriorityQueue 如同它的名字一般,多了 Priority 的功能,
在做 offer 的時候會依據物件的 Priority 來加進 Queue 裡,
這裡出現了第一個要注意的地方,有越小 Priority 的物件是排在比較前面的
也就是說當你透過 poll 來取得物件時,拿到的是當中最小的那個。
那如果想要取得的是 Priority 最大的怎麼辦?
有兩個方法,二擇一:
  1. 把有較大 Priority 的物件,定義較小的比較值。
  2. compare(T o1, T o2) 方法的結果反過來就行了。
    通常我們說當 o1 > o2 時,應該要回傳 > 0,這樣的結果 PriorityQueue 的排序就會是遞增的。如果想要遞減,當 o1 > o2 時,回傳 < 0 就行了。
PriorityQueue 其實是用最小堆積樹(Min Heap Tree)來實作的,從 source code 可以看出端倪:
k = size-1,x = 要插任的物件

587  private void siftUp(int k, E x) {
588      if ( != null)
589          siftUpUsingComparator(k, x);
590      else
591          siftUpComparable(k, x);
592  }
594  private void siftUpComparable(int k, E x) {
595      Comparable<? super E> key = (Comparable<? super E>) x;
596      while (k > 0) {
597          int parent = (k - 1) >>> 1;
598          Object e = [parent];
599          if (key.compareTo((E) e) >= 0)
600              break;
601          [k] = e;
602          k = parent;
603      }
604      [k] = key;
605  }
607  private void siftUpUsingComparator(int k, E x) {
608      while (k > 0) {
609          int parent = (k - 1) >>> 1;
610          Object e = [parent];
611          if (.compare(x, (E) e) >= 0)
612              break;
613          [k] = e;
614          k = parent;
615      }
616      [k] = x;
617  }
每次做 offer 時,都會呼叫 siftUp 來把物件加到樹中,過程如下圖所示:



而每次做 poll 時,都會呼叫 siftDown 來重新排序物件,過程如下圖所示:
k = 0,x = 最後一個物件
627  private void siftDown(int k, E x) {
628      if ( != null)
629          siftDownUsingComparator(k, x);
630      else
631          siftDownComparable(k, x);
632  }
634  private void siftDownComparable(int k, E x) {
635      Comparable<? super E> key = (Comparable<? super E>)x;
636      int half =  >>> 1;        // loop while a non-leaf
637      while (k < half) {
638          int child = (k << 1) + 1; // assume left child is least
639          Object c = [child];
640          int right = child + 1;
641          if (right <  &&
642              ((Comparable<? super E>) c).compareTo((E) [right]) > 0)
643              c = [child = right];
644          if (key.compareTo((E) c) <= 0)
645              break;
646          [k] = c;
647          k = child;
648      }
649      [k] = key;
650  }
652  private void siftDownUsingComparator(int k, E x) {
653      int half =  >>> 1;
654      while (k < half) {
655          int child = (k << 1) + 1;
656          Object c = [child];
657          int right = child + 1;
658          if (right <  &&
659              .compare((E) c, (E) [right]) > 0)
660              c = [child = right];
661          if (.compare(x, (E) c) <= 0)
662              break;
663          [k] = c;
664          k = child;
665      }
666      [k] = x;
667  }


第二個要注意的點來了!
已經加進 PriorityQueue 的物件可以隨意更動 Priority 嗎?
答案是 NO!!
隨意更動物件的 Priority,就破壞了原本樹的排序,接下來不管是 offer 或 poll 可能都是錯誤的結果。
此外,同樣 Priority 的物件是不保證順序的!