关闭

Android之界面刷新 View更新 Invalidate和postInvalidate的区别

标签: Android界面刷新Android界面更新InvalidatepostInvalidateInvalidate和postInval
318人阅读 评论(0) 收藏 举报
分类:

Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。 
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 


  Android程序中可以使用的界面刷新方法有两种,分别是利用Handler和利用postInvalidate()来实现在线程中刷新界面。 


1,利用invalidate()刷新界面 
  实例化一个Handler对象,并重写handleMessage方法调用invalidate()实现界面刷新;而在线程中通过sendMessage发送界面更新消息。 


// 在onCreate()中开启线程




new Thread(new GameThread()).start();、


// 实例化一个handler


Handler myHandler = new Handler() {
// 接收到消息后处理
public void handleMessage(Message msg) {
switch (msg.what) {
case Activity01.REFRESH:
mGameView.invalidate(); // 刷新界面
break;
}


super.handleMessage(msg);
}
};


class GameThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
Message message = new Message();
message.what = Activity01.REFRESH;
// 发送消息
Activity01.this.myHandler.sendMessage(message);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}


2,使用postInvalidate()刷新界面
 使用postInvalidate则比较简单,不需要handler,直接在线程中调用postInvalidate即可。


class GameThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}


// 使用postInvalidate可以直接在线程中更新界面
mGameView.postInvalidate();
}
}
}


 


View 类中postInvalidate()方法源码如下,可见它也是用到了handler的:
public void postInvalidate() {
        postInvalidateDelayed(0);
}


public void postInvalidateDelayed(long delayMilliseconds) {
        // We try only with the AttachInfo because there's no point in invalidating
        // if we are not attached to our window
        if (mAttachInfo != null) {
            Message msg = Message.obtain();
            msg.what = AttachInfo.INVALIDATE_MSG;
            msg.obj = this;
            mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
        }
    }






除了onCreate()是运行在UI线程上的,其实其他大部分方法都是运行在UI线程上的,其实其实只要你没有开启新的线程,你的代码基本上都运行在UI线程上。


完整例子:

  1. package com.czz.test;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Context;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Color;  
  7. import android.graphics.Paint;  
  8. import android.os.Bundle;  
  9. import android.os.Handler;  
  10. import android.os.Message;  
  11. import android.view.MotionEvent;  
  12. import android.view.View;  
  13. import android.widget.Toast;  
  14.   
  15. public class KeyDownActivity extends Activity {  
  16.   
  17.     private static final int REFRESH = 0x00001;  
  18.     GameView mGameView;  
  19.     @Override  
  20.     protected void onCreate(Bundle savedInstanceState) {  
  21.         // TODO Auto-generated method stub  
  22.         super.onCreate(savedInstanceState);  
  23.         mGameView = new GameView(this);  
  24.         this.setContentView(mGameView);  
  25.         new Thread(new GameThread()).start();  
  26.     }  
  27.   
  28.     @Override  
  29.     public boolean onTouchEvent(MotionEvent event) {  
  30.         // TODO Auto-generated method stub  
  31.         toast("touch position: "+event.getX()+","+event.getY());  
  32.         this.finish();  
  33.         return super.onTouchEvent(event);  
  34.     }  
  35.   
  36.     void toast(String text){  
  37.         Toast.makeText(KeyDownActivity.this, text, Toast.LENGTH_SHORT).show();  
  38.     }  
  39.     private class GameThread implements Runnable {  
  40.   
  41.         @Override  
  42.         public void run() {  
  43.             // TODO Auto-generated method stub  
  44.             while(!Thread.currentThread().isInterrupted()){  
  45.                 try{  
  46.                     Thread.sleep(400);  
  47.                 } catch(Exception e){  
  48.                     toast("GameThread error");  
  49.                     Thread.currentThread().interrupt();  
  50.                 }  
  51.                 //使用postInvalidate可以直接在线程中刷新  
  52.                 mGameView.postInvalidate();  
  53.             }  
  54.         }  
  55.           
  56.     }  
  57.     private class GameThreadOld implements Runnable{  
  58.   
  59.         @Override  
  60.         public void run() {  
  61.             // TODO Auto-generated method stub  
  62.             while(!Thread.currentThread().isInterrupted()){  
  63.                 try{  
  64.                     Thread.sleep(200);  
  65.                 } catch(Exception e){  
  66.                     toast("GameThread error");  
  67.                     Thread.currentThread().interrupt();  
  68.                 }  
  69.                 Message m = new Message();  
  70.                 m.what = KeyDownActivity.REFRESH;  
  71.                 KeyDownActivity.this.mHandler.sendMessage(m);  
  72.             }  
  73.         }  
  74.           
  75.     }  
  76.     private Handler mHandler = new Handler(){  
  77.   
  78.         @Override  
  79.         public void handleMessage(Message msg) {  
  80.             // TODO Auto-generated method stub  
  81.             switch(msg.what){  
  82.             case KeyDownActivity.REFRESH:  
  83.                 /*invalidate不能直接在线程中刷新,因为它违反了单线程模型: 
  84.                 Android的UI操作不是线程安全的,并且这些操作必须在UI线程中执行, 
  85.                 因此Android最常用的方法就是利用Handler来实现UI线程的刷新。*/  
  86.                 mGameView.invalidate();  
  87.                 break;  
  88.             }  
  89.             super.handleMessage(msg);  
  90.         }  
  91.           
  92.     };  
  93.     private class GameView extends View{  
  94.   
  95.         int mCount = 0;  
  96.         int y = 100;  
  97.         public GameView(Context context) {  
  98.             super(context);  
  99.             // TODO Auto-generated constructor stub  
  100.         }  
  101.   
  102.         @Override  
  103.         public void draw(Canvas canvas) {  
  104.             // TODO Auto-generated method stub  
  105.             super.draw(canvas);  
  106.             if(mCount < 10)  
  107.                 mCount++;  
  108.             else  
  109.                 mCount = 0;  
  110.             Paint mPaint = new Paint();  
  111.             switch(mCount % 4){  
  112.             case 0:mPaint.setColor(Color.RED);break;  
  113.             case 1:mPaint.setColor(Color.GREEN);break;  
  114.             case 2:mPaint.setColor(Color.BLUE);break;  
  115.             case 3:mPaint.setColor(Color.YELLOW);break;  
  116.             default:mPaint.setColor(Color.WHITE);break;  
  117.             }  
  118.               
  119.             canvas.drawRect((480-80)/2, y, (480-80)/2+80, y+40, mPaint);  
  120.         }  
  121.           
  122.     }  
  123. }  
感谢http://www.cnblogs.com/tt_mc/archive/2012/01/30/2332023.html

感谢http://blog.csdn.net/vincent_czz/article/details/7018725

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:62029次
    • 积分:1002
    • 等级:
    • 排名:千里之外
    • 原创:16篇
    • 转载:97篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论