2012-06-22 165 views
0

我正在尝试创建一个聊天程序,它将每2秒为新的聊天服务器拉动服务器。在线程中需要帮助

起初我只是简单地创建了一个线程并更新了线程中的ui,它崩溃了。

我添加了runnable,其中run方法调用了名为SendMessge的方法。 SendMessage通过互联网获取更新的通知,然后更新UI。

我虽然runnable中的run方法会在我的线程下运行,但它好像在ui线程上运行一样。

当我在发送消息中的网络代码错误时,UI冻结。

然后我设置了2个断点。一个在可运行之前,另一个在可运行之后。接下来,我在服务器上放置一个断点,以便网络代码可以freez。那么在android上,第一个断点就会熄灭,然后它在可运行后进入中断点,而不用等待我释放服务器上的brek点。因此,我假设runnable运行在不同的线程上,因为代码确实不要等待,我假设它的UI线程。

好吧,如果我有这个权利。在创建可运行之前,我的网络代码将在线程中。然后将在其运行方法中更新ui。问题,当我得到新的信息来更新用户界面,我如何将它发送到runnable的运行方法?

我的代码:

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.chat); 
    strComment=new String("na"); 
    mUsers=(TextView) findViewById(R.id.viewusers);; 
    mComments=(TextView) findViewById(R.id.viewchats); 
    mUserChat=(EditText) findViewById(R.id.viewedit); 
    mScroll=(ScrollView) findViewById(R.id.scrollcomments); 
    mHome=(Button) findViewById(R.id.butHome); 
    mHome.setOnClickListener(this); 
    mEnter=(Button) findViewById(R.id.butEnter); 
    mEnter.setOnClickListener(this); 

    Thread thread = new Thread(){ 
     @Override 
     public void run() { 
      try { 
       int t=0; 
       flagEnter=true; 
       while(true){ 
        handler.post(new Runnable() { 
        // I put a break point here 
         @Override 
         public void run() { 
          SendMessage(); 
         } 
        }); 
        // I put another break point here, it went right here without waiting for the sendmessage to finish 
        sleep(1000*10); 
        //while(true); 
       } 
      }catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 

    thread.start(); 
} 

public void onClick(View v) { 
    Intent i; 
    switch(v.getId()) { 
     case R.id.butEnter: 
      Editable e = mUserChat.getText(); 
      strComment=e.toString(); 
      flagAdd=true; 
      break; 
     case R.id.butHome: 
      i = new Intent(this, TellaFortuneActivity.class); 
      i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      startActivity(i);  
      break; 
    } 
} // end function 

// send a uypdate message to chat server 
// return reply in string 
void SendMessage(){ 
    ////////////////////////////////// 
    // handle flags 
    String de=new String(""); 
    String strUsers=new String(""); 
    String strComments=new String(""); 
    String comment=new String("NA"); 

    if (flagHome){ 
     Intent i; 
     i = new Intent(this, TellaFortuneActivity.class); 
     i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
     startActivity(i); 
     return; 
    } 

    String flag="update"; 
    if (flagAdd){ 
     // get new text 
     Editable text=mUserChat.getText(); 
     comment=text.toString(); 
     mUserChat.setText(""); 
     flag="add"; 
    } 

    if (flagEnter) 
     flag="enter"; 

    if (flagExit){ 
     flag="exit"; 
     flagHome=true; 
    } 

    // clear all flags 
    try { 
     URL url = new URL("http://50.63.66.138:1044/"+flag); 
     System.out.println("make connection"); 
     String data = URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode("tedpottel", "UTF-8"); 
     data += "&" + URLEncoder.encode("comment", "UTF-8") + "=" + URLEncoder.encode(comment, "UTF-8"); 
     URLConnection conn = url.openConnection(); 
     // set timeouts to 5 seconds 
     conn.setConnectTimeout(1000*5); 
     conn.setReadTimeout(5*1000); 
     conn.setDoOutput(true); 
     OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); 
     wr.write(data); 
     wr.flush(); 
     wr.close(); 

     // if (flagAdd==false){ 

     BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
     String line=new String(); 
     int state=0; 

     while ((line= rd.readLine() ) != null) { 
      de=de+line; 
      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: 
        // NOTE: end of comments is end, but...... 
        // if we do not read in ALL the dat from server 
        // could cause connection errors 
        if (line.contains("END COMMENTS")) 
         state=0; 
        else { 
         strComments+=line; 
         strComments+="\n"; 
        } 
        break; 
       } // end switch 
      } // end loop 
      rd.close(); 
     } 
     // 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()); 
    } 

    flagAdd=false; 
    flagEnter=false; 
    flagExit=false; 
} // end methed 

void Test(){ 
} 
+0

这可能是有点过分线程和轮询在你的主线程,可以考虑使用'Service'(它实际上并不难/复杂的),至少在投票。我做了这样的经验,只要你只使用1个活动,简单的线程就可以很好地工作,而不是更多。但是在一个'Service'中运行'ScheduledThreadPoolExecutor'进行轮询非常强大。 – trichner

回答

0

尝试使用的AsyncTask的线程的目的。谷歌为其最简单的教程 。

并确保你不要在一个线程和UI线程中做任何UI操作。始终为UI操作执行activity.runOnUiThread()。像

//获取新的文本

Editable text = mUserChat.getText(); 
comment = text.toString(); 
mUserChat.setText(""); 

这个代码必须在你的永恒主题在UI线程上运行。我从你在线程的run()方法内部调用的方法中获得了代码的和平。

在外部线程中。你必须做处理和数据工作。和UI更新必须在UI线程上完成,并且在UI线程上运行的东西始终使用activity.runOnUiThread()方法。

问候, Aqif哈米德