2012-06-22 125 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哈米德