2012-03-31 66 views
2

我正在使用一個應用程序,我只需要從mysql服務器下載一對谷歌地圖的座標。我可以成功地使用php和一個普通的httpost來做到這一點,但是當我這樣做時,我的應用程序凍結了幾秒鐘。異步HTTP發佈android

我讀到,你需要使得httppost asycronous以避免凍結,直到服務器完成prossess併發送結果。

問題是,我需要像普通的httpost這樣的json數組。

例如,如果我有這個httppost。

HttpClient httpclient = new DefaultHttpClient(); 
HttpPost httppost = new HttpPost("http://www.yoursite.com/script.php"); 

try { 
    // Add your data 
    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); 
    nameValuePairs.add(new BasicNameValuePair("id", "12345")); 
    nameValuePairs.add(new BasicNameValuePair("stringdata", "AndDev is Cool!")); 
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 

    // Execute HTTP Post Request 
    HttpResponse response = httpclient.execute(httppost); 
} catch (ClientProtocolException e) { 
    // TODO Auto-generated catch block 
} catch (IOException e) { 
    // TODO Auto-generated catch block 
} 

String result11 = null; 
// convert response to string 
try { 
    BufferedReader reader = new BufferedReader(new InputStreamReader(is11, "iso-8859-1"), 8); 
    StringBuilder sb = new StringBuilder(); 
    sb.append(reader.readLine() + "\n"); 
    String line = "0"; 
    while ((line = reader.readLine()) != null) { 
     sb.append(line + "\n"); 
    } 
    is11.close(); 
    result11 = sb.toString(); 
} catch (Exception e) { 
    Log.e("log_tag", "Error converting result " + e.toString()); 
} 

// parsing data 
try { 
    JSONArray jArray1 = new JSONArray(result11); 
} catch (JSONException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 

我如何可以轉換到異步職位,所以我能避免凍結?

+0

我不知道你的代碼可以怎麼連編譯,因爲它是,但請用['EntityUtils.toString(response.getEntity())'](http://stackoverflow.com/a/2324739/180740)而不是擁有自己的BufferedReader-n-StringBuilder派對。前者代碼少,具有正確的錯誤處理並服從服務器發送的字符編碼。 – 2012-03-31 09:27:12

回答

1

假設你想這樣做的一個按鈕點擊:

public void onClick(View v) { 
    new Thread(new Runnable() { 
     public void run() { 
      //your code here 
     } 
    }).start(); 
} 

基本上,你是把IO密集型操作一個單獨的線程(不是UI線程),從而使用戶界面不會凍結。

+0

嘗試在一段時間,病倒你回答。非常感謝您的迴應:) – user878813 2012-03-31 09:02:02

2

而不是隻是開始一個新的線程,它是一個更好的主意去與一個成熟的AsyncTask。它提供了更好的控制。

private class DoPostRequestAsync extends AsyncTask<URL, Void, String> { 
    protected String doInBackground(URL url) { 
     //Your download code here; work with the url parameter and then return the result 
     //which if I remember correctly from your code, is a string. 
     //This gets called and runs ON ANOTHER thread 
    } 

    protected void onPostExecute(String result) { 
     //This gets called on the interface (main) thread! 
     showDialog("Done! " + result); 
    } 
} 

將新的類實現放在所需的Activity類中。有關的AsyncTask更多信息請點擊以下鏈接:

http://developer.android.com/reference/android/os/AsyncTask.html

5

有一個很好的類AsyncTask它可以用來輕鬆運行異步任務。如果您在這樣的一個子類中嵌入代碼,你可能最終得到這樣的:

new FetchTask().execute(); 

其他資源:

  • Painless Threading - developer.android.com
  • public class FetchTask extends AsyncTask<Void, Void, JSONArray> { 
        @Override 
        protected JSONArray doInBackground(Void... params) { 
         try { 
          HttpClient httpclient = new DefaultHttpClient(); 
          HttpPost httppost = new HttpPost("http://www.yoursite.com/script.php"); 
    
          // Add your data 
          List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); 
          nameValuePairs.add(new BasicNameValuePair("id", "12345")); 
          nameValuePairs.add(new BasicNameValuePair("stringdata", "AndDev is Cool!")); 
          httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
    
          // Execute HTTP Post Request 
          HttpResponse response = httpclient.execute(httppost); 
    
          BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "iso-8859-1"), 8); 
          StringBuilder sb = new StringBuilder(); 
          sb.append(reader.readLine() + "\n"); 
          String line = "0"; 
          while ((line = reader.readLine()) != null) { 
           sb.append(line + "\n"); 
          } 
          reader.close(); 
          String result11 = sb.toString(); 
    
          // parsing data 
          return new JSONArray(result11); 
         } catch (Exception e) { 
          e.printStackTrace(); 
          return null; 
         } 
        } 
    
        @Override 
        protected void onPostExecute(JSONArray result) { 
         if (result != null) { 
          // do something 
         } else { 
          // error occured 
         } 
        } 
    } 
    

    可以使用啓動任務

  • AsyncTask - developer.android.com
3

我建議使用android-async-http(http://loopj.com/android-async-http/)庫。它使android異步http調用簡單而優雅。

+1

不幸的是,只有少數演示可用,這使得新手更容易理解如何將所有內容放在一起,例如在本例中將數據發佈到URL並使用JSON處理響應。我明白這一切都在那裏,似乎是非常強大和聰明,但更多的例子肯定會有所幫助。 – richey 2012-07-12 05:01:14

+1

我已經使用它,發現它很容易開始。我從http://loopj.com/android-async-http/中的「建議用法」一節中給出的代碼示例開始。我會一直學習並做某些事情,例如堅持cookies,使其與SSL(可信任和不可信任)協作,添加支票以查看設備是否在線等。我覺得所有這些問題都會必須處理你是否使用這個庫或Android API。 – krishnakumarp 2012-07-12 05:41:08

1

使用異步http庫,如離子。 https://github.com/koush/ion

所有的線程和異步樣板都會爲您處理。

這是你的代碼異步使用Ion。簡單得多:

Ion.with(context) 
.load("http://www.yoursite.com/script.php") 
.setBodyParameter("id", "12345") 
.setBodyParameter("stringdata", "AndDev is Cool!") 
.asJsonArray() 
.setCallback(new FutureCallback<JsonArray> { 
    void onCompleted(Exception e, JsonArray result) { 
    // do something with the result/exception 
    } 
});