2012-06-20 36 views
0

我正在尝试编写代码来每秒更新消息的服务器。邮件然后显示在文本视图中。如果我不更改文本视图中的文本,它运行良好。如果我尝试更改线程上的textview,它会崩溃。如果我改变它不在线程工作正常。我怎样才能从一个线程chnage TextViews文本?

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

在下面的代码中,我有一个线程,做一个无限循环与睡眠。它调用一个名为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 
} 
+0

你应该考虑'AsyncTask'而不是_thread_。 –

回答

0

您可以使用处理后的任务(的Runnable)的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(); 
    } 
} 
}; 
+0

嗨,在我假设SendMessage被调用时它正在运行的代码中在我创建的线程上没有UI?我问的原因是我的SendMessag有一个非常糟糕的错误,并且ui frooz。我会假设它是否在不同的线程上,用户界面不应该冻结? –

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

+0

在UIThread中运行线程?那会不会阻止UIThread? – Ixx

+0

是runOnUiThread不会阻止主UI线程 –

+0

@lxx请参阅doc http://developer.android.com/reference/java/lang/Runnable.html –

0

你不能从一个比一个不同的线程触摸的UI控件用于创建它(UI线程)。但如果你有到Activity一个参考,你可以简单地做:

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

这就需要strUsers是通过匿名类访问。对于您可以简单地这样做:

final String finalUseres = strUsers; 

和内run()使用finalUsers

0

尝试使用Service不断拉/发送数据到服务器。这将减少你的UI线程的负载。