0

我正在尝试编写代码以每秒拉服务器以获取更新的消息。然后消息会显示在文本视图中。如果我不更改文本视图中的文本,它运行良好。如果我尝试更改线程上的 textview,它将崩溃。如果我没有在线程上更改它可以正常工作。

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

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

代码:

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
}
4

5 回答 5

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
         }
        });

编辑: 见文档runOnUiThread

于 2012-06-20T18:41:43.023 回答
0

您不能从与用于创建它的线程(UI 线程)不同的线程中触摸 UI 小部件。但是,如果您有对 的引用Activity,您可以简单地执行以下操作:

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

这需要strUsers匿名类可以访问。为此,您可以简单地执行以下操作:

final String finalUseres = strUsers;

finalUsersrun().

于 2012-06-20T18:44:37.680 回答
0
the Andoid UI toolkit is not thread-safe. So, you  
must not manipulate your UI from a worker thread    

为了解决这个问题,Android 提供了几种从其他线程访问 UI 线程的方法。以下是可以提供帮助的方法列表:

你也可以使用AsyncTask

请参阅本教程关于 android 中的进程和线程

于 2012-06-20T18:45:15.453 回答
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();
    }
}
};
于 2012-06-20T18:47:55.083 回答
0

尝试使用 aService持续将数据拉/发送到服务器。这将减少 UI 线程的负载。

于 2012-06-20T18:48:24.843 回答