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的判断拉,所以就不会报错了呢。
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的判断拉,所以就不会报错了呢。
相关文章推荐
- Android编译时出现aapt.exe finished with non-zero exit value 1错误的解决方法
- 【解决】关于sscom不能保存当前窗口到文本文件的问题
- building workspace has encountered
- stl容器区别: vector list deque set map及底层实现
- UITableView的分割线长短的控制
- CodeForces 587E Duff as a Queen (线段树+线性基)
- jQueery-基础选择器
- 接口调用,输出结果为Json格式(ConvertTo-Json),提交参数给URL(WebRequest)
- 修改 Semantic UI 的默认字体
- Android Activity runonUiThread
- Poj2749 Building Roads
- UI进阶 FMDB
- 实在没想到系列——HashMap实现底层细节之keySet,values,entrySet的一个底层实现细节
- iOS——UICollectionView
- <GPS> Learning Neural Network Policies with Guided Policy Search under Unknown Dynamics
- UI(base)--android
- 更新UI 2种方法
- LeetCode-347.Top K Frequent Elements
- getParamValues()
- 普通类中获取request,session