2012-03-31 110 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 
    } 
});