顯示具有 [Android小筆記]一般 標籤的文章。 顯示所有文章
顯示具有 [Android小筆記]一般 標籤的文章。 顯示所有文章

2017年8月2日 星期三

CopyOnWriteArrayList的使用


  • 最近在Project上遇到一個問題,有一個ArrayList在讀取時偶發出現ConcurrentModificationException,這是因為不同Thread間剛好一個在寫入一個在讀取ArrayList,當然這可以用Mutex或Synchronize來解決,只是想估狗看看有沒有更好的方法,後來查到了原來有CopyOnWriteArrayList這個東西!


  • 它和ArrayList很像,但是有以下特性:


  1. 它是Thread-Safe
  2. 在做寫入時(add()/set()/remove())會複製一份出來改,overhead較大
  3. Iterator支持hasNext()/next()等的讀取動作,但不支持remove()等的寫入操作
  4. 使用Iterator掃過一遍List的速度很快
  • 它的內部實作是透過volatile的資料以及Mutex來達到Thread-Safe,並且寫入時複製一份做修改,改完再設回給volatile的資料。

  • 適用在List項目不會太多,讀取多,寫入少,會有Iterator掃過一遍且需要Thread-Safe的情況。


2014年7月25日 星期五

Weak References

Strong references
Strong reference是最常見的Java reference,舉例來說:
StringBuffer buffer = new StringBuffer();

  - 產生一個StringBuffer物件,並將一個strong reference存到buffer變數中。
  - strong指的是它和garbage collector的關係。
  - 如果一個物件是reachable via a chain of strong references,它就不適合被garbage collect。


When strong references are too strong
    當我們使用image cache時,若搭配strong reference,那麼這些image會一直保存在memory裡面。你必須自己決定何時不需要某個image並將它從cache中移除,但這樣的工作適合由garbage collection來處理的。


Weak references
    weak reference簡單地說就是一個不夠強的reference,無法強迫一個物件一直存留在memory中。它可以幫助garbage collector決定物件的reachability,所以你就不用自己做。以下為一個例子:

WeakReference<Widget> weakWidget = new WeakReference<Widget>(widget);

  - 可以使用weakWidget.get( )來取得實際的Widget物件。
  - 當這個widget物件沒有strong reference指向它時,可能會被garbage collection,此時weakWidget.get( )會return null。


  - 當你想追蹤Widget物件的序號,但Widget class中並沒有這個項目,而且也不允許extend它,此時可以用HashMap來處理:
serialNumberMap.put(widget, widgetSerialNumber);
  - 但如果當序號沒用的時候沒去移除entry,在沒有garbage collector的語言中會有memory leak。
  - 相同的我們也必須自己去管理這個HashMap何時該移除entry。

  - 可以改用WeakHashMap,它跟HashMap差在會把key (不是value)作為weak reference。
  -  當它的key變成garbage,則其value會自動被移除。


Reference queues
  - 一旦WeakReference開始return null,代表它所指到的物件已經變成garbage,也代表這個WeakReference不再被需要,所以此時可以做清理的動作。
  - 以WeakHashMap為例,要把已經沒用的entries移除。

  - ReferenceQueue class可便於追蹤這些dead references。
  - 若你把一個ReferenceQueue放到WeakReference的constructor,當reference所指的物件變成garbage了,則這個reference物件會自動插入reference queue中。你就可以每隔一段時間對這個ReferenceQueue做清理的動作。


Soft references
  - 一個物件只有在weakly reachable(最強的reference是WeakReference)才會在下一次的garbage collection cycle被丟棄。但softly reachable的物件還是會保留一段時間。
  - 實際上softly reachable的物件,只要memory足夠就會一直保留著。
  - 這對於製作cache是最好用的(例如image cache)。


Phantom references
  - 其get( ) method永遠return null
  - 它的用途只有在追蹤什麼時候被放入ReferenceQueue,也就是知道何時所指的object死了。

  - 它和WeakReference的差別在於enqueue的時機不同。
  - WeakReference是當object變成weakly reachable時去做enqueue,這個時間點是在finalization或garbage collection實際發生之前。理論上物件是可以藉由非正統的finalize() method來復活,但WeakReference仍然是死的。
  - PhantomReference只有在物件真正從memory中被移除時才會被enqueue。而get( ) method之所以永遠return null是為了避免你將物件復活。

  - PhantomReference的兩大用途:
    1. 得知物件何時真正從object中移除
        - 例如等到它真的發生,再去load下一張圖,確保OutOfMemory不會發生
    2. 避免在finalize( ) method中產生新的strong reference以復活物件的問題
        - 問題在於Override finalize( )的物件要在至少兩個garbage collection cycle才會被當作garbage。
        - finalization有可能不會及時執行,可能在等待finalization的過程中又經過了數個cycle,這代表實際上去清除garbage物件會有delay發生。這也是為什麼有時候,大部分的heap都是garbage但仍然發生OutOfMemory的原因。

強度:
Strong => Soft => Weak => Phantom


2014年7月21日 星期一

不用ValueAnimator改用TimerTask

問題:
有一個動畫,其中需要針對一個值的改變而畫,那個值會在650ms中照時間比例從0變到1,中間的值是float,作法如下。

mAnimator = ValueAnimator.ofFloat(0, 1);
mAnimator.setDuration(650);
mAnimator.addUpdateListener(...); // 每個animation的frame更新時都會callback
mAnimator.addListener(...); // animation的開始/結束/cancel/repeat
mAnimator.start();

但後來發現這個動畫會有卡頓的問題,並沒辦法均勻地變化比例。


解法:
所以我們改用TimerTask來做動畫,解決這個問題。

private Timer mTimer = new Timer(true); private MyTimerTask mTimerTask = new MyTimerTask(); public class MyTimerTask extends TimerTask{ @Override public void run() { if(mActivity != null){ mActivity.runOnUiThread(new Runnable(){ @Override public void run() { ..... } }); } } };

接著在要進行動畫的地方呼叫:
    mTimer.scheduleAtFixedRate(mTimerTask,...);

2014年7月15日 星期二

decodeFile/decodeStream的問題

decodeFile( )/decodeStream( )可能會有OutOfMemory exception的問題
所以改用decodeFileDescriptor( )會比較好
它呼叫與decodeFile( )/decodeStream( )不同的native function
其Bitmap不是用標準的Java方式去allocate的  應該是在virtual heap外另外allocate

參考資料:
http://www.cnblogs.com/akira90/archive/2013/03/15/2960666.html