2013-09-23 67 views
1

我試圖製作一個連接到服務器的Android應用程序(通過Socket),我相信我需要在不同的線程中完成它。但是,顯然,我無法從另一個線程訪問或修改Android UI。我該怎麼辦?Android多線程

package me.nrubin29.quiz.student; 

import android.app.Activity; 
import android.widget.Toast; 

import java.io.EOFException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 

public class Connection { 

    private Socket socket; 
    private Thread reader; 
    private ObjectInputStream inputStream; 
    private ObjectOutputStream outputStream; 

    public void initConnection(final Activity activity, final String ip, final String port, final String name) { 
     new Thread(new Runnable() { 
      public void run() { 
       try { 
        Toast.makeText(activity.getApplicationContext(), "Starting connection to " + ip + ":" + Integer.parseInt(port), Toast.LENGTH_SHORT).show(); 

        socket = new Socket(ip, Integer.parseInt(port)); 

        Toast.makeText(activity.getApplicationContext(), "Connected!", Toast.LENGTH_SHORT).show(); 

        outputStream = new ObjectOutputStream(socket.getOutputStream()); 

        inputStream = new ObjectInputStream(socket.getInputStream()); 

        outputStream.writeObject(name); 

        reader = new Thread(new Runnable() { 
         public void run() { 
          while (true) { 
           try { 
            Object in = inputStream.readObject(); 
            System.out.println(in); 
           } 
           catch (EOFException e) { Toast.makeText(activity.getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); } 
           catch (Exception e) { e.printStackTrace(); } 
          } 
         } 
        }); 

        reader.start(); 
       } 
       catch (Exception e) { e.printStackTrace(); } 
      } 
     }).start(); 
    } 
} 
+3

使用'runOnUiThread'這是您的活動類 – Raghunandan

+0

所以每當我想要做的任何事情* * GUI相關的,我應該使用該方法的方法是什麼? – nrubin29

+0

更多信息在這裏; https://developer.android.com/training/multiple-threads/communicate-ui.html – Krylez

回答

0

您可以使用runOnUiThread

activity.runOnUiThread(new Runnable() //run on ui thread 
{ 
    @Override 
    public void run() 
    { 
       // update ui 
    } 
}); 

http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)

public final void runOnUiThread (Runnable action) 

Added in API level 1 
Runs the specified action on the UI thread. If the current thread is the UI thread, then the action is executed immediately. If the current thread is not the UI thread, the action is posted to the event queue of the UI thread. 

Parameters 
action the action to run on the UI thread 
0

呼叫runOnUiThreadActivity你正在傳遞,這將發佈一條消息到UI線程。請記住,永遠不要向UI線程發佈消息需要很長時間才能執行,否則會鎖定您的應用,Android會提示用戶強制關閉它;即沒有網絡連接或繁重的計算。

一個例子:

activity.runOnUiThread(new Runnable() 
{ 
    @Override 
    public void run() 
    { 
      // Your UI stuff here 
    } 
}); 
0

有對付Android中「multithreadedness」的幾種方式,以及你的方法可以相應地改變你的需要。假設你只是使用一個簡單的java線程並且引用了你的活動(就像提供的例子一樣),你可以調用activity.runOnUiThread(Runnable r)並傳入要更新UI的runnable 。這實際上讓runnable在其他UI事件(例如動畫)之後執行。

處理它的另一個簡單方法是在您的Activity中調用「最終處理程序處理程序=新處理程序()」,並將此處理程序引用傳遞給線程。處理程序是一個特殊對象,與您的活動的UI線程綁定(從其調用時),並且可以提供一些方法將從後臺線程運行的可執行文件發佈到ui線程。

還有一種方法是使用AsyncTask,它是一個簡單的對象,它使您能夠在處理之前在UI線程上執行某些操作(如顯示加載對話框),然後在後臺線程上執行處理並然後在主線程上再次執行後臺處理的結果。這個cicle是onPreExecute() - > doInBackground() - > onPostExecute()。

還有其他方法,根據您的需要。

請提防的幾件事情:

活動有一個明確定義的生命週期,並且它們可能(或可能不會)死你的後臺處理髮生之前。您可能(或可能不)需要定義一些機制來檢查當您嘗試更新UI時活動是否仍然存在,否則您將遇到麻煩。 AsyncTask有一個非常有用的功能,可以根據您的onDestroy()活動接受取消,這就是簡單地在AsyncTask上對onDestroy()活動調用「cancel」並從AsyncTask中檢查這種取消。

根據您的使用情況,後臺線程可能(或可能不)持有對實際應該更多的內容的強烈引用。如果您要將您的活動的引用傳遞給後臺線程或AsyncTask,我建議從java中查看WeakReference。

根據您的平臺版本,觸發多個同步AsyncTasks的線程條件可能(或可能不)以異步或同步處理結束。

0

修改UI線程有很多方法,其中之一是將消息推送到處理程序。

Handler handler = new Handler(){ 

    public void handleMessage(Message msg){ 
    //Perform yor UI Modification 
    } 

}

handler.sendMessage(msg);