关闭

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

标签: UI更新非UI线程更新UI为什么只有UI
220人阅读 评论(0) 收藏 举报
分类:
更新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的判断拉,所以就不会报错了呢。
1
0

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