2013-04-24 852 views
4

我是android.I'm的新手,通過WiFi監聽傳入的消息,它適用於監聽和更新用戶界面,但是當我嘗試退出它並不響應後退按鈕直到它在緩衝區中接收到消息。從我的理解,按鈕是在UI線程和Runnable是一個單獨的線程,這就是爲什麼它不響應按鈕按立即因爲忙於單獨的線程。那麼,我怎麼能打斷後退按鈕按下「Runnable」?如何停止或退出「Runnable」

任何幫助將不勝感激。

public Runnable mUpdate = new Runnable() { 
    public void run() {    
     try { 
      line = in.readLine(); 
      newtext.setText(line); 
      mHandler.post(this); 
      Log.i("RESPONSE FROM SERVER", "S: Received Message: '" +line+ "'"); 

      //onBackPressed(); 
      //threadRunning = true; 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      Log.e("Error" , "Something Happen");  
     } 
    } 
}; 

編輯:對不起,我應該張貼此較早,所以在「的onCreate」,我使用的處理程序來調用「mUpdate」。這是否是正確的方式?

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    intent = getIntent(); 
    setContentView(R.layout.activity_display_message); 
    message = intent.getStringArrayExtra(MainActivity.EXTRA_MESSAGE); 
    newtext = (TextView)findViewById(R.id.TextView1); 
    userName = message[0]; 
    serverIP = message[1]; 
    sendConnectionRequest(); 
    mHandler = new Handler(); // Handler to update UI  
    mHandler.post(mUpdate);  // post is a method to update UI 

    } 

回答

2

編輯:

現在你已經補充說,涉及Handler它現在更清晰的地方你的麻煩就在於代碼。幾點理解:

  • Android有一個總的概念,有主線程,然後還有很多其他的線程。
  • 只有主線程可以修改UI
  • 在主線程不允許做網絡的Android的更新版本...

因此,如何根據從網絡上讀一些更改UI ?

您需要將來自其他(網絡)線程的消息傳遞給主線程。處理程序讓您的其他線程給主線程發送消息...這就是您的網絡線程可以給主線程執行任務(Runnable)。處理程序將任務從網絡線程發佈到主線程。

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    intent = getIntent(); 
    setContentView(R.layout.activity_display_message); 
    message = intent.getStringArrayExtra(MainActivity.EXTRA_MESSAGE); 
    newtext = (TextView)findViewById(R.id.TextView1); 
    userName = message[0]; 
    serverIP = message[1]; 
    sendConnectionRequest(); 
    mHandler = new Handler(); // Handler to update UI 
           // This is being created in the main thread 
           // so everything posted will be posted to 
           // the main thread 

    mUpdate.start();   // start thread to do something on the network 
           //before updating the UI 

} 

public Thread mUpdate = new Thread() { 
    public void run() {    
     try { 
      while (!thread.interrupted()) { 
       final String line = in.readLine(); 
       Log.i("RESPONSE FROM SERVER", "S: Received Message: '" +line+ "'"); 

       // Define the UI change you want to make 
       Runnable uiUpdate = new Runnable() { 
        public void run() { 
         // modify your UI here. 
         newtext.setText(line); 
        } 
       }; 

       // post the UI change back to the main thread. 
       mHandler.post(uiUpdate); 
      } 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      Log.e("Error" , "Something Happen");  
     } 
    } 

    public void interrupt() { 
     try { 
      super.interrupt(); 
      in.close(); 
     } 
     catch (IOException e) {} 
    } 
}; 

可能我建議你也:

protected void onDestroy() { 
    mUpdate.interrupt(); 
} 

原來的答覆(現已解散)

從我的理解,按鈕都在UI線程和Runnable接口是一個獨立的線程,這就是爲什麼它沒有立即響應按鈕按下它在繁忙的單獨線程上。

這是不正確的。 A Thread是一個單獨的線程,不是Runnable。並且您需要在線程上調用start()而不是run()以使run方法在其自己的線程中執行。使用線程的關鍵點是一個線程不會(通常)被另一個線程阻塞。

// <snip>removed for brevity of new answer</snip> 

您還可以查看android庫中的AsyncTask。如果您正確使用它,它也將在其自己的線程中運行。

+0

'中斷()'只將中斷標誌。執行的代碼負責檢查該標誌並正確終止。 – afk5min 2013-04-24 11:32:32

+0

@ afk5min是和否。雖然在這種情況下比沒有更多。它根據線程的當前狀態具有其他效果。我修改瞭解決此問題的答案。 http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#close%28%29 – 2013-04-24 11:41:14

+0

如果線程處於阻塞等待狀態,則會生成InterruptedException - 但該異常被檢查;被執行的代碼被迫處理這種情況。 (另外,上面的例子不使用阻塞等待) – afk5min 2013-04-24 11:45:29

-1

我不知道這與Android有什麼關係,但從您的標題來看,停止Java中的線程是由中斷執行的,中斷由操作系統本身處理。

從你線程你打斷另一個。

theOtherThread.interrupt() //--> inside your Thread. 

而在另一邊:

public void run(){ 
    while(true){ 
      try{ 
       //handle your logic 
       Thread.sleep(100); 
      }catch(InterruptedException){ 
      //thread was 'stopped' here 
      Thread.currentThread().interrupt(); //this is a MUST 
      break; 
     } 
    } 
} 
+0

只有'Thread#stop()'方法使用JVM/native方法來終止正在執行的線程。 'interrupt()'只是設置線程中斷標誌,不做其他任何事情。 – afk5min 2013-04-24 11:35:03

+0

@ afk5min ups。我忘了添加while(true)循環。看我的編輯。這會讓你快樂嗎?如果不是一些本地apis(POSIX線程,Solaris線程,Windows線程等),您如何看待內部完成的中斷?設置一個標誌*可能是真實的,但它取決於實現,並且javadoc中沒有關於該標誌的內容。 ;) – Eugene 2013-04-24 12:03:03

+0

@這很有趣!不,實際上,閱讀Android項目和非Android項目的中斷文檔。他們不同。這就是爲什麼我開始「我不知道這是否與Android有關」。 :) P.S.在中斷被捕獲之後,我也忘記了那裏的break語句,我甚至沒有編譯這個 - 只是在PLAIN JAVA中它應該用中斷來完成。 – Eugene 2013-04-24 16:00:54