2016年1月12日 星期二

SurfaceView的動畫會閃爍破碎......用同一個迴圈完成Draw和Post

在Android上,要能夠將Draw和Post分開,必須要另外產生一張Canvas。
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
Post時,只需要在lockCanvas所取到的Canvas上「畫一次」Bitmap(b)即可。

不懂?



如果有十個物件要繪製,從lockCanvas到PostCanvas這中間進行這十次的繪製動作,會導致畫面開始延遲和閃爍。

但如果把這十次縮減成一次,從lockCanvas到PostCanvas這中間所花的時間也就只需要十分之一,畫面更新效率理論上會提升...至少三倍?



野心大的人可能會把進行Draw的Canvas也搬到另一個Thread中進行。

那就會有兩個Thread,一個是DrawThread,一個是PostThread。

但如果畫面更新率不統一,PostThread中要執行Draw時DrawThread也進行Draw了,則Post畫面上使用的Bitmap可能就會被回收......破碎跟黑塊可能就是這樣來的.......



但,在高段的遊戲繪圖領域中,確實是用多個Thread來處理繪圖。

但那恐怕是純Thread的領域,跟繪不繪圖並沒有太直接的關係。

SurfaceView的透明背景一片黑...要將Bitmap屬性設為Config.ARGB_4444

1.在ViewHolder上設定setFormat(PixelFormat.TRANSLUCENT);
2.在畫上想要的內容前先執行canvas.drawColor(Color.TRANSPARENT,Mode.CLEAR);

執行了這兩個步驟後,還是經常有人拿到一片黑的背景。

這是因為作為繪圖用的Bitmap,Bitmap.createBitmap()這個函數中傳入的可能是RGB_565。

改為ARGB_4444後就解決了。



對了!

記得打硬體加速的設定打開!

在AndroidManifest檔中,在Application標籤內加入android:hardwareAccelerated="true"。

2016年1月6日 星期三

HashMap的Key和Value

雖然Key也可以丟物件型態的資料進去,包含String,但令人驚訝(但其實又不驚訝)的是「它不會比對內容」。

例如用字串「Test」當Key值,丟進去了一個物件A,之後再用一個新的、但內容一樣的字串「Test」去搜尋,會發現找不到物件A。

(也就是說:它是用HashKey值作為Key......所以叫「Hash」Map?)



這也挺合理。

今天如果是用String以外的物件(假設為類別1)做Key,然後內有N個參數,然後用實體A來做為Key值存放Value,──HashMap怎麼知道當使用者修改了參數值後,實體A還是同一個Key值?而接下來存入的資料要存放在新欄位?還是取代舊資料?

如果要讓HashMap的Key值有辨識內容的功能,這大概會變成無限迴圈跑不完,(萬一類別1的參數又有物件型態的資料時,是否又要再分析一次...)



根據以上特性,HashMap除了作為存放跟取用的容器以外,是否也可以快速地幫忙比對資料?

譬如類別2內有M組參數,但我們只需要比對其中M1/M2/M3/M4...

再設計一個類別3,內有N組參數可以存放M1/M2/M3/M4...

用類別3的實體物件為Key、類別2的實體物件為Value,類別3實體物件參數值設定跟類別2實體物件一樣,然後直接判讀Key來判斷是否需要取用內容?

public static class KeyObj2{
  
 int a, b, c, d, e, f, g;
  
}
 
public static class KeyObj3{
  
 int a, b, c, d, e;
  
}


類似這樣兩組物件...另外再準備一個矩陣,長度為5,剛好可以存放N組參數。

這同時也需要兩個HashMap(A/B),一個是以矩陣為Key,另一個是以類別3為Key,但Value都是類別2。

然後在準備一個單純的List,用來直接存放類別2。

將HashMap的Key值已Set<T>的方式取出來,(怕有人不知道:它有內建函數可以輸出Set<T>。)然後再用for(T : Set)的方式判讀裡面的結果........

至於List的內容,就直接用for(... : ...)判讀即可,不需要再取出值。



以物件為Key值,執行的效率比以矩陣為Key值快了.......一成左右!

聽起來好像很不賴,但List直接取個別值出來判讀內容,只需要以物件為Key值的2成...不是快兩成,是只需要兩成。

顯然不管怎麼設計,用HashMap就是無法做到快速比對內容!(與其試圖智慧化,不如單一化、線性化,這真是程式設計的黃金法則!)



另外,物件的Class值也是個Hash,而且只會以實體物件宣告的方式為主,不會被多型性所干擾。(但這是Java,在其他也有提供Collection類別的程式語言上,不知道情況如何。)

所以用HashMap<Class, ObjectA>的方式在ObjectA中設置一個static型態的HashMap,就可以用來存放所有ObjectA的子類別的SingleTon參數,不需要再每個子類別中設計不一樣的static參數或static函數去取得SingleTon參數。