2010-01-07 11 views
11

Ich erstelle eine Android-Anwendung, die Webanfragen im Hintergrund ausführen und dann die empfangenen Daten bearbeiten und die Benutzeroberfläche entsprechend der Serverantwort ändern muss.Wie Webanforderung in einem eigenen Thread ausführen?

Das Ziel, Anfragen zu stellen und Daten im Hintergrund zu bearbeiten, besteht darin, das Einfrieren der Benutzeroberfläche zu vermeiden. Momentan merke ich jedoch, dass die Benutzeroberfläche friert, daher bin ich mir nicht sicher, ob die Logik so funktioniert, wie sie soll.

Hier ist der Teil des Codes, die Anforderungen schreiben sollte, und die Antworten in einem eigenen Thread zu verarbeiten und dann die Daten an GUI übergeben:

public class ServerConnection { 

Queue<String> requests; 

... 

DefaultHttpClient httpClient; 
HttpHost targetHost; 

Handler handler; 

ServerResponseHandler responseHandler; 
Activity activity; 

public ServerConnection(Activity activity){ 
    this.activity = activity; 
    this.responseHandler = (ServerResponseHandler) activity; 
    httpClient = new DefaultHttpClient(); 
    targetHost = new HttpHost(TARGET_DOMAIN, 80, "http"); 
    requests = new LinkedList<String>(); 
} 



private Runnable requestSender = new Runnable(){ 

    @Override 
    public void run() { 
     if(!requests.isEmpty()){ 
      String requestString = requests.remove(); 
      HttpGet httpGet = new HttpGet(requestString); 
      httpGet.addHeader("Accept", "text/xml"); 
      String encodingString = "testuser:testpass"; 
      String sEncodedString = Base64Coder.encodeString(encodingString); 

      try{ 

       String sContent = fetchURL(requestString, sEncodedString); 

       XMLParser xmlParser = new XMLParser(); 

       List <Product> products = xmlParser.getProducts(sContent); 

       responseHandler.onProductsResponse(products); 
      } 
      catch(Exception ex){ 
       Log.e(TAG, ex.getMessage()); 
      } 
     } 
    } 
}; 

public void sendRequest(String requestString){ 
    requests.add(requestString); 
    handler = new Handler(); 
    handler.post(requestSender); 
} 

Verfahren sendrequest() aus der Haupttätigkeit genannt wird, die implementiert ServerResponseHandler. Ich nehme an, die Anfrage wird in einem eigenen Thread ausgeführt und durch den Aufruf

responseHandler.onProductsResponse (Produkte);

Die Liste der Produkte (Daten aus dem Internet) wird an die Hauptaktivität übergeben. Aufgrund der schlechten Leistung würde ich mich freuen, wenn irgendjemand ein mögliches Problem in der obigen Logik korrigieren oder eine andere (bessere) Option vorschlagen könnte.

Antwort

21

Ich würde vorschlagen, dass Sie sich ASyncTask class ansehen (verfügbar seit Android 1.5).

Es vereinfacht das Erstellen eines Hintergrundthreads, der mit dem GUI-Thread synchronisiert wird, sobald er abgeschlossen ist.

Sie sollten in der Lage sein, zu erreichen, was Sie versuchen, etwas Liste mit Code, um diesen

private class DownloadFilesTask extends AsyncTask<String, List<Product>, Integer> { 
    protected List<Products> doInBackground(String... requestStrings) { 
     int count = requestStrings.length; 
     int results = 0; 
     for (int i = 0; i < count; i++) { 
      String requestString = requestStrings[i]; 
      HttpGet httpGet = new HttpGet(requestString); 
      httpGet.addHeader("Accept", "text/xml"); 
      String encodingString = "testuser:testpass"; 
      String sEncodedString = Base64Coder.encodeString(encodingString); 
      try{ 
      String sContent = fetchURL(requestString, sEncodedString); 
      XMLParser xmlParser = new XMLParser(); 
      List <Product> products = xmlParser.getProducts(sContent); 
      results++; 
      publishProgress(products); 
      } 
      catch(Exception ex){ 
      Log.e(TAG, ex.getMessage()); 
      } 
     } 
     return results; 
    } 

    protected void onProgressUpdate(Integer... progress) { 
     // TODO You are on the GUI thread, and the first element in 
     // the progress parameter contains the last progress 
     // published from doInBackground, so update your GUI 
    } 

    protected void onPostExecute(int result) { 
     // Processing is complete, result contains the number of 
     // results you processed 
    } 
} 

und führt durch

new DownloadFilesTask().execute(url1, url2, url3); 
+0

Asynctask oder Handler + Thread, es liegt an dir Niko – tbruyelle

+2

AsyncTask ist der Weg zu gehen. –

+0

Es sind nette Lösungen – kablu

0

Aufruf Nach den handler javadoc, ich glaube nicht, das post() Methode erstellen Sie beliebige Threads. Wenn ich recht habe, führe die Runnable auf dem Thread aus, an den der Handler angeschlossen ist. In diesem Fall ist dies der Aktivitäts-Thread, also der UI-Thread! Deshalb haben Sie schlechte Leistung.

Sie müssen eine Thread implementieren, die Ihre Runnable ausführen. Aber das zu tun, werden Sie nicht in der Lage sein, Ihre Aktivität zu aktualisieren, wie Sie gerade tun durch den Aufruf:

responseHandler.onProductsResponse(products); 

Dies ist, weil Sie nicht mehr in dem UI-Thread sind, und nur der UI-Thread ist ermächtigt, interagieren mit der Benutzeroberfläche (also die Aktivität). Sie müssen also diesen Anruf durch Zugriff auf Ihre Handler ersetzen.

Message msg = handler.obtainMessage(); 
Bundle bundle = new Bundle(); 
bundle.putSerializable("products", products); //not sure it will pass here 
msg.setData(bundle); 
handler.sendMessage(msg); 

und Umsetzung der handleMessage() Methode für Ihre Handler:

@Override 
public void handleMessage(Message msg) 
{ 
    List <Product> products = msg.getData().getSerializable("products"); 
    responseHandler.onProductsResponse(products); 
} 

Last but not least: die Handler hat noch in der Tätigkeit Thread erstellt werden.

Verwandte Themen