Android:无法从Thread中访问视图

时间:2014-08-08 23:21:58

标签: android multithreading android-asynctask

我正在尝试编写一个简单的应用程序示例,该示例将运行for循环,每次将其计数器递增1,然后使用计数器i的当前值更新视图并打印出来: " i =#" 我收到一条错误消息,指出您无法更新未在该线程中创建的视图。我试图通过从线程内部膨胀视图并通过创建一个新的TextView并调用" setContentView(myTextView)"来解决这个问题。但这些都没有解决问题。 我尝试了一个使用AsyncTask的不同版本,但我不知道如何将代码划分为每个AsyncTask的方法。有人可以帮助我看看如何做到这一点,因为它告诉我,我在这一点上的理解中缺少。 谢谢 爱德华 PS。 inflater和setContentView的注释掉的行来自我尝试修复它。

我原来尝试的代码是试图更新我的TextView" myTextView"在应用程序的主要布局中:

public void loopForever(View view) {

        Thread thread = new Thread(){
            public void run(){

                // LayoutInflater inflater = null;     
                // inflater.inflate(R.layout.activity_main, null);

                TextView myTextView;
                myTextView = (TextView) findViewById(R.id.myTextView);
                // setContentView(myTextView)

                for(int i = 0; i < 1000; i++){
                    myTextView.setText("i = " + i);
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        thread.start();
}

3 个答案:

答案 0 :(得分:1)

您只能从UI线程(活动,片段等回调)中访问View元素。您可以切换到Asynctask并通过postexecute或发布进度回调(http://developer.android.com/reference/android/os/AsyncTask.html)进行UI更改,或者使用runOnUiThread,例如:

public void loopForever(View view) {

    Thread thread = new Thread(){
        public void run(){
            for(int i = 0; i < 1000; i++){
                activity.runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
                  (TextView) activity.findViewById(R.id.myTextView).setText("i = " + i);
                 }
                });
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    thread.start();
}

答案 1 :(得分:1)

正如其他用户所说,您无法从主线程以外的任何线程更新用户界面元素。你应该使用视图类post()或postDelayed()方法,你的代码应该是这样的:

for(int i = 0; i < 1000; i++){

    myTextView.postDelayed(new Runnable(){

        public void run(){

           myTextView.setText("i = " + i);
        }  

    }, 1000);
}

这是一个链接: http://developer.android.com/reference/android/view/View.html#post(java.lang.Runnable)

您可能还想看一下android异步任务类 http://developer.android.com/reference/android/os/AsyncTask.html

答案 2 :(得分:0)

您必须从&#34; UI线程&#34;更新用户界面(UI)元素,例如TextView。您无法从其他线程(例如您所创建的线程)更新它们。

This Android lesson可能对您有用:

  

每个应用都有自己的特殊线程来运行UI对象,例如View对象;这个线程称为UI线程。只有在UI线程上运行的对象才能访问该线程上的其他对象。由于您在线程池中的线程上运行的任务未在UI线程上运行,因此它们无法访问UI对象。要将数据从后台线程移动到UI线程,请使用在UI线程上运行的处理程序。

如果您使用AsyncTask,则可以覆盖onProgressUpdate(Progress...)方法来更新TextView。故意在UI线程上运行onProgressUpdate(Progress...)以允许此操作。