在Android实际开发中,我们常常需要进行View的刷新(例如:自定义控件等),Android中为我们提供了两组刷新View的方法—-Invalidate和postInvalidate,前者是在UI线程中更新View,而后者是在非UI线程中更新VIew,两组方法的具体区别如下介绍:
我们都知道,在Android中,更新UI的操作要在UI线程(也就是主线程)中进行,因为Android UI操作并不是线程安全的,但是这些操作必须在UI线程中调用(单线程模式,这里就不在详细介绍了,可以自己上网查阅)。

Invalidate()方法:

对于初学者来说,我们常用的更新UI的方式不外乎就是利用Handler机制,在工作线程中执行耗时操作等,然后发消息给UI线程,进行UI操作。以下我们以自定义控件来介绍该用法(自定义控件,实现一个圆环不停的刷新大小,由小变大):
自定义控件,绘制一个圆环,并更新其大小“`

public class MyView extends View {    /** * 画笔 */    private Paint mPaint ;    /** * 自定义控件半径 */    private int radiu ;    public MyView(Context context) {        this(context, null);    }       public MyView(Context context, AttributeSet attrs) {        super(context, attrs);        // 初始化画笔        initPaint() ;    }    public MyView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    /** * 初始化画笔方法 */    private void initPaint() {        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG) ;        mPaint.setStyle(Style.STROKE) ;        mPaint.setColor(Color.RED) ;        mPaint.setStrokeWidth(20) ;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        // 执行绘制        canvas.drawCircle(150, 150, radiu, mPaint) ;    }    public synchronized void setRadiu(int radiu) {        this.radiu = radiu ;            // 刷新,即重新绘制        invalidate() ;    }}

然后在MainActivity中:

public class MainActivity extends Activity {    /** * 自定义控件对象 */    private MyView myView ;    /** * 自定义控件的半径 */    private int radiu ;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        myView = (MyView) findViewById(R.id.myview) ;        // 开启线程        new Thread(new Runnable() {            @Override            public void run() {                try {                    // 死循环,不停的刷新View                    while(true) {                        // 当半径小于200时,开始自增                        if(radiu <= 200) {                            radiu += 10 ;                            // 发送消息给Handler处理                              mHandler.obtainMessage().sendToTarget() ;                        } else {                            radiu = 0 ;                        }                        // 每隔40毫秒睡一次                        Thread.sleep(40) ;                    }                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }).start() ;    }    @SuppressLint("HandlerLeak")    private Handler mHandler = new Handler() {        public void handleMessage(android.os.Message msg) {            // 设置自定义控件的半径            myView.setRadiu(radiu) ;        };    } ;    protected void onDestroy() {        super.onDestroy() ;        // 界面销毁后移除Handler的引用        mHandler.removeCallbacksAndMessages(null) ;    };}

以上这种方式即为在非UI线程中执行逻辑代码,然后利用Handler机制发送消息通知UI线程进行更新UI的操作。

postInvalidate()方法:

而postInvalidate()可以直接在非UI线程中刷新,不需要使用Handler机制,代码逻辑也相对比较简单:

public class MyView extends View implements Runnable {    /** * 画笔 */    private Paint mPaint ;    /** * 自定义控件半径 */    private int radiu ;    public MyView(Context context) {        this(context, null);    }    public MyView(Context context, AttributeSet attrs) {        super(context, attrs);        // 初始化画笔        initPaint() ;    }    public MyView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    /** * 初始化画笔方法 */    private void initPaint() {        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG) ;        mPaint.setStyle(Style.STROKE) ;        mPaint.setColor(Color.RED) ;        mPaint.setStrokeWidth(20) ;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        // 执行绘制        canvas.drawCircle(150, 150, radiu, mPaint) ;    }    @Override    public void run() {        while(true) {            try {                if(radiu <= 150) {                    radiu += 10 ;                    postInvalidate() ;                } else {                    radiu = 0 ;                }                Thread.sleep(40) ;            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}   

在MainActivity中,开启线程更新View:

public class MainActivity extends Activity {    /** * 自定义控件对象 */    private MyView myView ;    /** * 自定义控件的半径 */    private int radiu ;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        myView = (MyView) findViewById(R.id.myview) ;        // 开启线程刷新界面        new Thread(myView).start() ;    }

以上两种方式,是我在利用自定义控件时使用的,可能对于不熟悉自定义控件的初学者来说看着会有点乱,其实仔细阅读以下,就会发现,并不是那么难,第一种方式中,我们选择利用Handler机制来处理,利用消息机制来通知UI线程更新View操作,所以,调用Invalidate()的方法(即setRadiu())是运行在UI线程的,对于第二种方法,我们将更新View的方法放在了一个子线程中(即Runnable接口的run方法中),然后在调用该自定义控件时开启一个线程来操作,所以postInvalidate()方法是运行在子线程的。
我们在学习Android时,要记住一点,代码千变万化,万变不离其宗,代码稍微一改就会不一样,但其调用的实质是一样的。希望这篇博客能给大家一点帮助,若有解释不合理的地方,希望大家提出宝贵的意见。

更多相关文章

  1. android:padding 和 android:margin的区别
  2. Android(安卓)NDK 面试题汇总
  3. Android消息机制
  4. android中刷新Invalidate和postInvalidate的区别
  5. Android(安卓)Handler机制详解:在线程中新建Handler
  6. 安卓中一些常用的属性小结
  7. 利用HTML5开发Android笔记(中篇)
  8. Android工程中R.java文件的重新生成——注意资源文件的错误
  9. 【Android】动态链接库so的加载原理

随机推荐

  1. Android(安卓)Activity应用窗口的创建过
  2. Android(安卓)API Guides---Administrati
  3. AppWidget开发实例讲解(一)
  4. Android中结合OrmLite for android组件对
  5. 【讲座】It's Android(安卓)Time:程序员创
  6. Android(安卓)开发之android架构
  7. Android仿人人客户端(v5.7.1)——新鲜事之
  8. android单元测试AndroidTestCase
  9. Android(安卓)播放Gif 动画
  10. R文件没了怎么办