如何从线程更改TextView文本?

时间:2012-06-20 18:38:31

标签: android

我正在尝试编写代码来每秒为服务器提取更新的消息。然后,消息将显示在文本视图中。如果我不更改文本视图中的文本它运行正常。如果我尝试更改线程上的textview,它将崩溃。如果我改变它不在线程上工作正常。

我假设线程无法访问主线程内存?如何在视图中设置刚刚通过互联网加载的文本?

在下面的代码中,我有一个线程,它通过睡眠进行无限循环。它调用一个名为SendMessage的方法。发送消息通过Internet加载文本,最后尝试使用它更新视图。发生这种情况时会引发异常。

代码:

public class cChat extends cBase  implements OnClickListener {
    /** Called when the activity is first created. */
      TextView mUsers; 
      TextView mComments; 
      int i=0;

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.chat);

            mUsers=( TextView) findViewById(R.id.viewusers);;
            mComments=( TextView) findViewById(R.id.viewchats);;

          Thread thread = new Thread()
          {
              @Override
              public void run() {
                  try {
                      int t=0;
                      while(true) 
                      {
                          SendMessage();
                          sleep(1000*5);
                          t++;
                      }
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          };

          thread.start();

        }


       public void onClick(View v) {


           } // end function



        // send a uypdate message to chat server 
        // return reply in string
        void SendMessage()
        {


            try {


            URL url = new URL("http://50.63.66.138:1044/update");
               System.out.println("make connection");

               URLConnection conn = url.openConnection();
               // set timeouts to 5 seconds
               conn.setConnectTimeout(1000*5);
               conn.setReadTimeout(5*1000);
               conn.setDoOutput(true);
               BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));


            //   String line;
               String strUsers=new String("");
               String strComments=new String("");
               String line=new String();
               int state=0;
               while ((line= rd.readLine()  ) != null) {
                 switch(state){
                 case 0:
                   if ( line.contains("START USER"))
                     state=1;
                   if ( line.contains("START COMMENTS"))
                     state=2;
                   break;
                 case 1:
                   if ( line.contains("END USER"))
                         state=0;
                   else
                   {
                   strUsers+=line;
                   strUsers+="\n";
                   }
                   break;
                 case 2:
                       if ( line.contains("END COMMENTS"))
                             state=0;
                       else {
                       strComments+=line;
                       strComments+="\n";
                       }
                       break;
                 } // end switch   
               } // end loop

      // the next line will cause a exception
               mUsers.setText(strUsers);
               mComments.setText(strComments);

        } catch (Exception e) {
             i++; // use this to see if it goes here in debugger  
            //   System.out.println("exception");
           //    System.out.println(e.getMessage());
           }

        } // end methed
}

5 个答案:

答案 0 :(得分:3)

将runOnUiThread用作

 YOUR_CURRENT_ACTIVITY.this.runOnUiThread(new Runnable() {

         @Override
         public void run() {
         // the next line will cause a exception
           mUsers.setText(strUsers);
           mComments.setText(strComments);
            //....YOUR UI ELEMENTS
         }
        });

编辑: 见doc runOnUiThread

答案 1 :(得分:0)

您无法从不同于创建它的线程(UI线程)触摸UI小部件。但是,如果你有Activity的引用,你可以这样做:

activity.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        mUsers.setText(strUsers);
        mComments.setText(strComments);
    }
});

这将要求匿名类可以访问strUsers。为此你可以做到:

final String finalUseres = strUsers;

并在finalUsers内使用run()

答案 2 :(得分:0)

the Andoid UI toolkit is not thread-safe. So, you  
must not manipulate your UI from a worker thread    

要解决此问题,Android提供了几种从其他线程访问UI线程的方法。以下列出了可以提供帮助的方法:

您也可以使用AsyncTask

请参阅this tutorial on process and threads in android

答案 3 :(得分:0)

您可以使用处理程序将任务(Runnables)发布到UI /主线程:

private Handler handler = new Handler();

//...

Thread thread = new Thread()
{
@Override
public void run() {
    try {
        int t=0;
        while(true) 
        {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    SendMessage();
                }
            });

            sleep(1000*5);
            t++;
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
};

答案 4 :(得分:0)

尝试使用Service连续向服务器提取/发送数据。这将减少UI-Thread的负载。