UI更新的方法和在非UI线程里面,怎么更新UI信息。细细的

原创 2016年06月01日 22:29:48
更新UI的几种方式:
runOnUiThread;
Handler post;
handler sendMessage;
view post;
第一种方法:Handler post:
public class FiveActivity extends Activity {
    private TextView textView;
    private Handler handler new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.five);
        textView = (TextView) findViewById(R.id.tv1);
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
               catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("更新完成");
                    }
                });
            }
        }.start();
    }
}    
理解:程序运行,然后直走,进入线程UI线程显示当前内容,子线程等待,然后通过,handler.post更新显示内容(在主线程中执行);
第二种方法handler sendMessage :
public class FiveActivity extends Activity {
    private TextView textView;
    private Handler handler new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            textView.setText("更新完成");
           
        }
    };

    private void handler2(){
        handler.sendEmptyMessage(1);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.five);
        textView = (TextView) findViewById(R.id.tv1);
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    handler2();
               catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }.start();
    }
}
理解:程序运行,UI线程显示当前内容,子线程运行到handler.sendEmptyMessage(1)时候,给handler发送指令,然后更新完成。其中testView.setText在主线程中运行,其他步骤在子线程中运行。
第三种方法runOnUiThread :
    private void update(){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                textView.setText("更新完成");
                Log.d("test""线程:" + Thread.currentThread());
            }
        });
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.five);
        textView = (TextView) findViewById(R.id.tv1);
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    update();
               catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }.start();
    }
}
理解:程序运行——>执行子线程——>执行到update方法的时候,UI更新;(testView.setText在主线程中运行)
第四种方法view post :
 private void viewUI(){
        textView.post(new Runnable() {
            @Override
            public void run() {
                textView.setText("更新完成");
                Log.d("test""线程:" + Thread.currentThread());
            }
        });
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.five);
        textView = (TextView) findViewById(R.id.tv1);
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    viewUI();
               catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }.start();
    }
}
理解:程序运行——>执行子线程——>执行到viewUI方法的时候,UI更新;(testView.setText在主线程中运行)


非UI线程更新UI的方法:
     
public class SixActivity extends Activity {
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.six);
        textView= (TextView) findViewById(R.id.textView2);
        new Thread(){
            @Override
            public void run() {
                textView.setText("就更新你了,咋地");
                Log.d("test","线程:"+Thread.currentThread());
            }
        }.start();
    }
}
  对,这就是非UI线程更新UI的方法,什么都别加 ,赤裸裸的。但是这是为什么呢,我们就一起去看看吧!
我们都知道,所有更新UI的方法,都会调用view的invalidate方法;
public void invalidate() {
    invalidate(true);
}
void invalidate(boolean invalidateCache) {
    invalidateInternal(00mRight mLeftmBottom mTopinvalidateCache, true);
}

void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
        boolean fullInvalidate) {
    if (mGhostView != null) {
        mGhostView.invalidate(true);
        return;
    }

    if (skipInvalidate()) {
        return;
    }

    if ((mPrivateFlags & (PFLAG_DRAWN PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN PFLAG_HAS_BOUNDS)
            || (invalidateCache && (mPrivateFlags PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
            || (mPrivateFlags PFLAG_INVALIDATED) != PFLAG_INVALIDATED
            || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
        if (fullInvalidate) {
            mLastIsOpaque = isOpaque();
            mPrivateFlags &= ~PFLAG_DRAWN;
        }

        mPrivateFlags |= PFLAG_DIRTY;

        if (invalidateCache) {
            mPrivateFlags |= PFLAG_INVALIDATED;
            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
        }

        // Propagate the damage rectangle to the parent view.
        final AttachInfo ai = mAttachInfo;
        final ViewParent p = mParent;
        if (p != null && ai != null && l < r && t < b) {
            final Rect damage = ai.mTmpInvalRect;
            damage.set(ltrb);
            p.invalidateChild(this, damage);
        }

        // Damage the entire projection receiver, if necessary.
        if (mBackground != null && mBackground.isProjected()) {
            final View receiver = getProjectionReceiver();
            if (receiver != null) {
                receiver.damageInParent();
            }
        }

        // Damage the entire IsolatedZVolume receiving this view's shadow.
        if (isHardwareAccelerated() && getZ() != 0) {
            damageShadowReceiver();
        }
    }
}
     其中关键的是ViewParent。然后,在ViewParent里面有个叫做InvalidateChildlnParent的方法,在这个方法中呢,有个checkThread的方法,这个就是拿来检查线程的;他的工作原理:在他的方法里面,会有一个判断,也就是
     if(mThread!=Thread.curremtThread){
          throw new Call………………………………(太长了,不想打了,就是用子线程更新UI而看到的异常。)
}
那么问题来了,当前线程没有休眠的时候呢,为什么就可以更新线程了呢?
那是因为Activity有个 ViewRootImpl他在onResume中创建,因为程序先走的是onCreate,所以,这ViewRootImpl 还没有被创建出来,也就不会进行
checkThread的判断拉,所以就不会报错了呢。
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

子线程中更新UI线程的三种方法

  • 2014年11月17日 14:06
  • 1.39MB
  • 下载

C# Winform 跨线程更新UI控件常用方法汇总

 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件的线程访问它”的异常。处理跨线程更新Winform UI控件常用的方法有4种: ...

Android_子线程创建消息队列更新UI

  • 2015年12月07日 00:16
  • 2.53MB
  • 下载

WPF 使用线程更新UI

  • 2014年11月30日 15:47
  • 61KB
  • 下载

C# Winform 跨线程更新UI控件常用方法总结

C# Winform 跨线程更新UI控件常用方法总结(转) 出处:http://www.tuicool.com/articles/FNzURb 概述 C#Winform编程中,跨线程直接更新...

C# Winform 跨线程更新UI控件常用方法总结(转)

出处:http://www.tuicool.com/articles/FNzURb 概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建...
  • dragoo1
  • dragoo1
  • 2017年02月10日 12:35
  • 1413

Android子线程中更新UI的3种方法

Android子线程中更新UI的3种方法转自:http://j.news.163.com/docs/99/2014090316/A582RD1M9001RD1N.html 在Android项目中经常...
  • shangsd
  • shangsd
  • 2015年06月08日 20:55
  • 283

知识梳理:Android子线程中更新UI的3种方法

在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法:  在看方法之前看一下Android中消息机制:    ...
  • jsonnan
  • jsonnan
  • 2016年05月03日 22:32
  • 475

[转]C#子线程更新UI控件的方法实例总结

[我的评论:之前项目做的C#客户端对于多线程修改UI使用的就是这个,找了好些时间才找到,其他很多都是没有再函数中直接使用Action [来源:http://www.jb51.net/article/...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:UI更新的方法和在非UI线程里面,怎么更新UI信息。细细的
举报原因:
原因补充:

(最多只允许输入30个字)