Android之view重繪
http://qaohao.javaeye.com/blog/478314
關鍵字: android
android中實現view的更新有兩組方法,一組是invalidate,另一組是postInvalidate,其中前者是在UI線程自身中使用,而後者在非UI線程中使用。
以下是我在android文檔中找到的說明,
引用
public void invalidate()
Invalidate the whole view. If the view is visible, onDraw(Canvas)
will be called at some point in the future. This must be called from a
UI thread. To call from a non-UI thread, call postInvalidate().
public void postInvalidate ()
Cause an invalidate to happen on a subsequent cycle through the
event loop. Use this to invalidate the View from a non-UI thread.
google的文檔的說明實在是簡單,往往看了開發中都會遇到這兩個問題:
1. 沒有任何異常,view沒能重新整理。
2. android應用異常終止,開啟logcat會看到這樣的異常資訊, Only the original thread that created a view hierarchy can touch its views。
最後,通過查文檔,上網查詢才知道,invalidate和postInvalidate方法需要使用android提供的handler,才能
實現重繪,而在文檔的說明中卻隻字不提,真是簡單啊。具體是在需要重繪的地方調用handler的sendMessage方法發送訊息,緊接著會os會觸
發handler中的handlerMessage方法,在handlerMessage方法中再調用view的invalidate或者
postInvalidate方法就能實現重繪。
下面是我分別針對invalidate方法,給出view重繪代碼,僅供參考:
Java代碼
- class
CustomizeView
extends
WhichView {
-
- public
CustomizeView(Context context) {
- super
(context);
- final
Handler handler =
new
Handler();
-
- new
Thread(
new
Runnable() {
- @Override
- public
void
run() {
- // delay some minutes you desire.
- /*try {
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- }*/
- handler.post(new
Runnable() {
- public
void
run() {
- concreteUpdateUI();
- invalidate();
- }
- });
- }
- }).start();
- }
-
- protected
void
concreteUpdateUI() {
- // Add concrete movement for UI updates.
- // ...
- }
- }
class CustomizeView extends WhichView {public CustomizeView(Context context) {super(context);final Handler handler = new Handler();new Thread(new Runnable() {@Overridepublic void run() {// delay some minutes you desire./*try {Thread.sleep(3000);} catch (InterruptedException e) {}*/handler.post(new Runnable() {public void run() {concreteUpdateUI();invalidate();}});}}).start();}protected void concreteUpdateUI() {// Add concrete movement for UI updates.// ...}}
或者這樣實現也可以。
Java代碼
- class
CustomizeView
extends
TextView {
-
- public
CustomizeView(Context context) {
- super
(context);
- new
Thread(
new
UIUpdateThread()).start();
- }
-
- class
UIUpdateThread
implements
Runnable {
- final
Handler mHandler =
new
Handler();
-
- final
Runnable mUpdateResults =
new
Runnable() {
- public
void
run() {
- concreteUpdateUI();
- invalidate();
- }
- };
-
- public
void
run() {
- // delay some minutes you desire.
- /*try {
- Thread.sleep(1000 * 5);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }*/
- mHandler.post(mUpdateResults);
- }
-
- }
-
- protected
void
concreteUpdateUI() {
- // Add concrete movement for UI updates.
- // ...
- }
-
- }
我上面提供的代碼,只是一個架子,這個架子裡面只能實現兩種情形:
1)其一就是android控制項延時重新整理,修改方法就是在UIUpdateThread類的run方法在呼出Handler的post方法之前增加一個延遲。
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
舉個例子說明一下它在什麼場合應用吧,比如啟動遊戲前的動畫,是不是Imageview就可以通過這個延時重新整理來實現啟動動畫的效果,剛開始載入一幅畫,過會換一幅畫。
2)其二就是android控制項定時重新整理,那就得在修改CustomizeView構造方法,將UIUpdateThread添加到Timer中,這樣就可以實現定時重新整理。
那麼如果你需要不定時重新整理的話,那我提供的這個架子就不適用了,你得自己去調用Handler的post方法。這種情況應該是最常見的。
class CustomizeView extends TextView {public CustomizeView(Context context) {super(context);new Thread(new UIUpdateThread()).start();}class UIUpdateThread implements Runnable {final Handler mHandler = new Handler();final Runnable mUpdateResults = new Runnable() {public void run() {concreteUpdateUI();invalidate();}};public void run() {// delay some minutes you desire. /*try {Thread.sleep(1000 * 5);} catch (InterruptedException e) {e.printStackTrace();}*/mHandler.post(mUpdateResults);}}protected void concreteUpdateUI() {// Add concrete movement for UI updates. // ... }}