您的位置:首页 > 产品设计 > UI/UE

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

2016-06-01 22:29 323 查看
更新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(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, 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(l, t, r, b);

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的判断拉,所以就不会报错了呢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息