public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView show = (TextView)findViewById(R.id.show);
new Thread()
{
@Override
public void run()
{
show.setText("子线程更新UI");
}
}.start();
}不是说在新建的线程中不能更新UI吗?为什么我在UI线程中新建了一个线程还能够更新成功?
有劳各位了!

解决方案 »

  1.   

    Android 为了限制子线程更新UI, 设置了线程的检查机制,
    例如从子线程对Textview.setText,
    通过报错的log能看出, 抛出异常的位置是在android.view.ViewRoot.checkThread()(),从字面的意思看,这个方法就是用来检查修改view的Thread()是否主线程。
    这个检查方法在view的requestLayout()里面被调用,但是requestLayout()有些情况下不会被调用:
    if(mParent != null){
        if (!mParent.isLayoutRequested()) {
             mParent.requestLayout();
       }
    }
     
    唯一的解释就是以上2个if中的一个不符合,导致后面的checkThread()()没被调用,子线程就成功地修改了界面UI。
     这个可能是在activity 被创建的初期,layout或者其他动作初始化还没有完成,导致线程的检查没有发生,具体的问题就要去研究下才知道了。
     
    你可以试一下, 你的第一种情况,在new Thread 修改textview之前让线程睡眠2秒,这时候再来修改UI就会抛出异常了。
      

  2.   

    如果将这段代码放入到一个按钮的单击事件中,他是会首先将布局显示出来,紧接着就会报异常的
    new Thread()
            {
                @Override
                public void run()
                {
                    show.setText("子线程更新UI");
                }
            }.start();从实现上来讲子线程是可以更改布局界面的,只是在代码只做了限制,更新ui的时候会判断线程是不是主线程,如果不是就报异常,这是一种机制。
    其实如果在模拟器上运行的时侯,即使将上面这段代码放入按钮的单击事件里,也会将   “子线程更新UI”显示出来,然后才报错的。