当前位置:编程学习 > wap >>

谁说非UI线程不能更新View的?

package NotUIThread_UpdateNotWrong.sonyChinaese.run;

import mythread.UpdateTextViewThread;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class Main extends Activity {
private TextView textView1;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView1 = (TextView) this.findViewById(R.id.textView1);

Log.v("!Main", "" + Thread.currentThread().getName() + " "
+ Thread.currentThread().getId());

UpdateTextViewThread mythread = new UpdateTextViewThread();
mythread.setTextView1(textView1);
mythread.start();

}
}


----------
package mythread;

import android.util.Log;
import android.widget.TextView;

public class UpdateTextViewThread extends Thread {

private TextView textView1;

public void setTextView1(TextView textView1) {
this.textView1 = textView1;
}

@Override
public void run() {
super.run();
Log.v("!run", "" + Thread.currentThread().getName() + " "
+ Thread.currentThread().getId());
textView1.setText("aaaaaaaaaaaaaaaaaaaa");
}


}
--------------------编程问答-------------------- 不报异常么? --------------------编程问答-------------------- 不能sleep,还只能放在onCreate里面做,其实意义不大,等大牛解释 --------------------编程问答-------------------- --------------------编程问答-------------------- 能跑吗? 很怀疑 --------------------编程问答-------------------- 本来就是能更新view的啊。。
就是容易出现卡机现象。。
--------------------编程问答-------------------- 肯定会报异常的,难道现在Android可以使用多线程更新UI控件了? --------------------编程问答-------------------- 程序根本没有报错!!!!!
--------------------编程问答-------------------- 等大牛解答~ --------------------编程问答-------------------- 你在线程里加个sleep(2000),或者把Thread放到 onStart里,你看会不会出错。还是好好研究下Activity生命周期吧。各个周期明白都干了什么你就知道为什么不出错了。 --------------------编程问答-------------------- 因为你的textview在settext的时候还没有显示,整个activity大概还没有进入onstart阶段。你弄个循环在textview已经显示了之后再修改试试 --------------------编程问答-------------------- onCreate算是UI线程吧!? --------------------编程问答-------------------- 经测试,可以在非主线程里面对界面信息进行设置,但是:非主线程不能直接刷新主线程的界面,否则就会报异常android.view.ViewRoot$CalledFromWrongThreadException。
贴上测试代码:
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
new Thread() {
public void run() {
super.run();
TextView tx = (TextView) findViewById(R.id.textView);
tx.setText("lllllllllllllllllllll");
}

}.start();

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread() {
public void run() {
super.run();
TextView tx = (TextView) findViewById(R.id.textView);
tx.setText("2222222222222");
}

}.start();
}
});
}

--------------------编程问答-------------------- 注:这段代码是在setContentView()之后;当点击button后才会报错 --------------------编程问答-------------------- 再注:“可以在非主线程里面对界面信息进行设置”这句话有问题 --------------------编程问答-------------------- 因为你的线程只做了一件事情 就结束了,,你在线程里面写个循环 然后在循环里面 更新文本 试试看~~ --------------------编程问答--------------------    其实在后台线程中访问UI控件本来就是不一定报错的。
    但是在操作的过程中,比较容易发生异常,而导致程序变得很卡(变得很卡是没有调试器连接的情况,如果程序是在调试状态运行,那么这个时候eclipse会告诉你发生了CalledFromWrongThreadException),这个概率么,说不上来,但是如果后台线程如果是循环执行这个访问操作就很容易遇到。
    像楼主这种只执行一次的情况,遇到的概率不高。 --------------------编程问答--------------------
引用 15 楼 birdsaction 的回复:
因为你的线程只做了一件事情 就结束了,,你在线程里面写个循环 然后在循环里面 更新文本 试试看~~



protected void onStart() {
// TODO Auto-generated method stub

super.onStart();

TextView tx = (TextView) findViewById(R.id.textView);
tx.setText("aaaaaaaaaaa");

new Thread() {
public void run() {
super.run();
TextView tx = (TextView) findViewById(R.id.textView);
for (int i = 0; i < 3; i++) {
tx.setText("lllllllllllllllllllll" + i);
}

}

}.start();

Button button = (Button) findViewById(R.id.button);

button.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread() {
public void run() {
super.run();
TextView tx = (TextView) findViewById(R.id.textView);
tx.setText("2222222222222");
}

}.start();
}
});
}

结论一样,只有在点击按钮之后才报错 --------------------编程问答-------------------- 讨论以上问题没有任何意义,本人声明是来灌水啊。
每天回帖,增加积分! --------------------编程问答--------------------
引用 16 楼 a220315410 的回复:
   其实在后台线程中访问UI控件本来就是不一定报错的。
    但是在操作的过程中,比较容易发生异常,而导致程序变得很卡(变得很卡是没有调试器连接的情况,如果程序是在调试状态运行,那么这个时候eclipse会告诉你发生了CalledFromWrongThreadException),这个概率么,说不上来,但是如果后台线程如果是循环执行这个访问操作就很容易遇到。
    像楼主这种只执行一次……


nonono,当我点击按钮之后是100%报错的 --------------------编程问答-------------------- 咋能说木有意义呢,可以增加对Activity的了解嘛。

我的理解是:非主线程可以对界面信息进行更新,但是不能进行刷新。在Activity执行完onResume()之前,界面实际上是没画好的,所以可以随便进行更新。执行完onResume()之后,界面就算画好了,这时候刷新界面的事情只能让ui线程干了。

对or错? --------------------编程问答-------------------- 跟:
runOnUiThread(new Runnable{
    public void run(){
      text.setText("---");
    }
});

有区别吗 ?? --------------------编程问答-------------------- Android提供了UI线程 ,最好不要在 线程里面更新UI,,这样做不保险。。做实际的项目千万别做就好。 --------------------编程问答--------------------
引用 20 楼 xing376688 的回复:
咋能说木有意义呢,可以增加对Activity的了解嘛。

我的理解是:非主线程可以对界面信息进行更新,但是不能进行刷新。在Activity执行完onResume()之前,界面实际上是没画好的,所以可以随便进行更新。执行完onResume()之后,界面就算画好了,这时候刷新界面的事情只能让ui线程干了。

对or错?


正解,点名表扬! --------------------编程问答-------------------- 不死不代表不会死
不会死不代表一定不死 --------------------编程问答--------------------



引用 23 楼 seker_xinjian 的回复:
[Quote=引用   20   楼   xing376688   的回复:]

咋能说木有意义呢,可以增加对Activity的了解嘛。

我的理解是:非主线程可以对界面信息进行更新,但是不能进行刷新。在Activity执行完onResume()之前,界面实际上是没画好的,所以可以随便进行更新。执行完onResume()之后,界面就算画好了,这时候刷新界面的事情只能让ui线程干了。

……
--------------------编程问答-------------------- the Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread --------------------编程问答-------------------- 用handler不行么? 我就是这么用的 就是在页面显示出来之后再来动态的改变ui 实际改变的代码还是放在ui线程里面
package com.hundsun.zhoujl.android;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class TestUIChangeActivityActivity extends Activity {

private TextView tv = null;
private Handler handler = null;

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tv = (TextView)findViewById(R.id.tv);
        handler = new Handler() {

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tv.setText("Hello Handler");
}
        
        };
        Thread thread = new Thread() {

@Override
public void run() {
super.run();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0);
}
        
        };
        thread.start();
    }
}

--------------------编程问答-------------------- 不能更新的意思并不是说用户更新不了,而是更新的时候有安全隐患。
打个比喻:你不能考试。 这并不是说你没有考试的能力,而是因为其他的原因而不准去考试。你个人再体会体会吧。 --------------------编程问答-------------------- 这个没看明白。。。 --------------------编程问答-------------------- 这么做,容易出现ANR。 --------------------编程问答--------------------
引用 20 楼 xing376688 的回复:
咋能说木有意义呢,可以增加对Activity的了解嘛。

我的理解是:非主线程可以对界面信息进行更新,但是不能进行刷新。在Activity执行完onResume()之前,界面实际上是没画好的,所以可以随便进行更新。执行完onResume()之后,界面就算画好了,这时候刷新界面的事情只能让ui线程干了。

对or错?

这个答案比较贴近,我记得在一篇介绍handler looper messagequeue的文章中讲过,在OnCreate这个事件中其他线程是可以更新UI的,但在其他On中就一定会报错 --------------------编程问答-------------------- --------------------编程问答--------------------
引用 32 楼 aomandeshangxiao 的回复:


大牛出现了,求详细解析啊~~ --------------------编程问答-------------------- View不是线程安全的吧。会有data racing的问题。

多线程编程,最基本的问题就是同步加锁等解决data race。 当然data race的时候,大部分情况下不会死,也可能会做对,但由于两个线程间互相不知道对方对自己要管理的资源做了什么手脚,会出现很多奇怪的问题。 --------------------编程问答-------------------- 可以但是会出现问题,因为View不是线程安全 --------------------编程问答-------------------- 摆脱你的UpdateTextViewThread  也是UI线程,
你不会以为 UI线程就是看不见的吧

看不见的线程,但拥有的 View组件的也算 UI线程好不好。。。 --------------------编程问答-------------------- 不懂啊 最近被搞的头都大了  --------------------编程问答-------------------- 可以看下源码 
View 的线程检测机制在ViewRootIml类的checkThread()方法中,
void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }
ViewRootIml是接口ViewParent的实现,它会在requestFitSystemWindows()、requestLayout()、invalidateChildInParent(int[] location, Rect dirty)、requestTransparentRegion(View child)、requestChildFocus(View child, View focused)、clearChildFocus(View child)、focusableViewAvailable(View v)、recomputeViewAttributes(View child)、playSoundEffect(int effectId)、focusSearch(View focused, int direction)、doDie()方法中进行检查的
View中大部分方法都是基于ViewParent(指向ViewRootIml的引用),这个检测机制在某个特定的条件下是不会检查的~ --------------------编程问答-------------------- 顶!顶!顶!顶!
补充:移动开发 ,  Android
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,