android中Invalidate和postInvalidate的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android中Invalidate和postInvalidate的区别相关的知识,希望对你有一定的参考价值。

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

1,利用invalidate()刷新界面

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

public class TestActivity extends Activity
    private View view;
    public class Handler handler = new Handler()
        public void handleMessage(Message msg) 
          view.invalidate(); // 刷新界面
       
   
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread()
    public void run()
        handler.sendEmptyMessage();
    
.start();
   


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

public class TestActivity extends Activity
    private View view;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread()
    public void run()
        view.postInvalidate();
    
.start();
   


两个方法都有重载函数,用于刷新指定区域的内容

public void invalidate(int l, int t, int r, int b) ;

 public void invalidate(Rect dirty) ;

public void postInvalidate(int l, int t, int r, int b) ;

 public void postInvalidate(Rect dirty) ;

此外postInvalidate还支持延迟刷新,

public void postInvalidateDelayed(long delayMilliseconds)

让视图在指定时间后刷新

参考技术A 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();
本回答被提问者和网友采纳

Android开发 View的UI刷新Invalidate和postInvalidate

Invalidate

正常刷新

/**
     * 使整个视图无效。如果视图可见,
     * @link #onDraw(android.graphics.Canvas) 调用此方法后将在后续的UI刷新里调用onDraw(android.graphics.Canvas)方法
     * <p>
     * 必须从UI线程调用此方法。要从非UI线程调用,请调用@link #postInvalidate().*/
    public void invalidate() 
        invalidate(true);
    

    /**
     * This is where the invalidate() work actually happens. A full invalidate()
     * causes the drawing cache to be invalidated, but this function can be
     * called with invalidateCache set to false to skip that invalidation step
     * for cases that do not need it (for example, a component that remains at
     * the same dimensions with the same content).
     *
     * @param invalidateCache Whether the drawing cache for this view should be
     *            invalidated as well. This is usually true for a full
     *            invalidate, but may be set to false if the View‘s contents or
     *            dimensions have not changed.
     * @hide
     */
    public void invalidate(boolean invalidateCache) 
        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
    

一些解释

1.首先invalidate() 也是调用 invalidate(boolean invalidateCache) 这个方法的,只有设置为true时才会让这个View刷新

2.上面的注释已经说了invalidate()的刷新是必需在UI线程的

设置布局位置,重新调整View的刷新位置

/**
     * Mark the area defined by dirty as needing to be drawn. If the view is
     * visible, @link #onDraw(android.graphics.Canvas) will be called at some
     * point in the future.
     * <p>
     * This must be called from a UI thread. To call from a non-UI thread, call
     * @link #postInvalidate().
     * <p>
     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
     * @code dirty.
     *
     * @param dirty the rectangle representing the bounds of the dirty region
     *
     * @deprecated The switch to hardware accelerated rendering in API 14 reduced
     * the importance of the dirty rectangle. In API 21 the given rectangle is
     * ignored entirely in favor of an internally-calculated area instead.
     * Because of this, clients are encouraged to just call @link #invalidate().
     */
    @Deprecated
    public void invalidate(Rect dirty) 
        final int scrollX = mScrollX;
        final int scrollY = mScrollY;
        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
    

    /**
     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
     * coordinates of the dirty rect are relative to the view. If the view is
     * visible, @link #onDraw(android.graphics.Canvas) will be called at some
     * point in the future.
     * <p>
     * This must be called from a UI thread. To call from a non-UI thread, call
     * @link #postInvalidate().
     *
     * @param l the left position of the dirty region
     * @param t the top position of the dirty region
     * @param r the right position of the dirty region
     * @param b the bottom position of the dirty region
     *
     * @deprecated The switch to hardware accelerated rendering in API 14 reduced
     * the importance of the dirty rectangle. In API 21 the given rectangle is
     * ignored entirely in favor of an internally-calculated area instead.
     * Because of this, clients are encouraged to just call @link #invalidate().
     */
    @Deprecated
    public void invalidate(int l, int t, int r, int b) 
        final int scrollX = mScrollX;
        final int scrollY = mScrollY;
        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
    

 

postInvalidate

这个方法可以非UI线程中调用

正常刷新

/**
     * <p>导致在事件循环的后续循环中发生无效。使用此选项使非UI线程中的View无效</p>
     *
     * <p>仅当此视图附加到窗口时,才能从UI线程*外部调用此方法。</p>
     *
     * @see #invalidate()
     * @see #postInvalidateDelayed(long)
     */
    public void postInvalidate() 
        postInvalidateDelayed(0);
    

改变位置后刷新

/**
     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
     *
     * <p>This method can be invoked from outside of the UI thread
     * only when this View is attached to a window.</p>
     *
     * @param left The left coordinate of the rectangle to invalidate.
     * @param top The top coordinate of the rectangle to invalidate.
     * @param right The right coordinate of the rectangle to invalidate.
     * @param bottom The bottom coordinate of the rectangle to invalidate.
     *
     * @see #invalidate(int, int, int, int)
     * @see #invalidate(Rect)
     * @see #postInvalidateDelayed(long, int, int, int, int)
     */
    public void postInvalidate(int left, int top, int right, int bottom) 
        postInvalidateDelayed(0, left, top, right, bottom);
    

延迟刷新

/**
     * <p>导致在事件*循环的后续循环中发生无效。等待指定的时间。</p>
     *
     * <p>This method can be invoked from outside of the UI thread
     * only when this View is attached to a window.</p>
     *
     * @param delayMilliseconds the duration in milliseconds to delay the
     *         invalidation by
     *
     * @see #invalidate()
     * @see #postInvalidate()
     */
    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
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) 
            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
        
    

改变位置,并且延迟刷新

/**
     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
     * through the event loop. Waits for the specified amount of time.</p>
     *
     * <p>This method can be invoked from outside of the UI thread
     * only when this View is attached to a window.</p>
     *
     * @param delayMilliseconds the duration in milliseconds to delay the
     *         invalidation by
     * @param left The left coordinate of the rectangle to invalidate.
     * @param top The top coordinate of the rectangle to invalidate.
     * @param right The right coordinate of the rectangle to invalidate.
     * @param bottom The bottom coordinate of the rectangle to invalidate.
     *
     * @see #invalidate(int, int, int, int)
     * @see #invalidate(Rect)
     * @see #postInvalidate(int, int, int, int)
     */
    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
            int right, int bottom) 

        // We try only with the AttachInfo because there‘s no point in invalidating
        // if we are not attached to our window
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) 
            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
            info.target = this;
            info.left = left;
            info.top = top;
            info.right = right;
            info.bottom = bottom;

            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
        
    

 

 

 

 

 

end

以上是关于android中Invalidate和postInvalidate的区别的主要内容,如果未能解决你的问题,请参考以下文章

android中Invalidate和postInvalidate的差别

android中Invalidate和postInvalidate的区别

android中Invalidate和postInvalidate的区别

invalidate和postInvalidate 的区别及使用

android中Invalidate和postInvalidate的区别

android中Invalidate和postInvalidate的区别