2012-04-18 52 views
0

我有一個JSON文件(towns.json)坐在我的服務器上,在我的應用程序中,我希望從那裏讀取數據。 所以我想通了,我應該使用AsyncTask不阻止UI線程。我這樣做如下:Android:在AsyncTask中發佈JSON

private class GetTowns extends AsyncTask<String, String, Void> { 
    protected void onPreExecute() {} 

    @Override 
    protected Void doInBackground(String... params) { 
     String readTown = readFeed(ScreenStart.this, "http://server.com/towns.json"); 
     try { 
      JSONArray jsonArray = new JSONArray(readTown); 
      town = new ObjectTown[jsonArray.length()]; 
      for (int i = 0; i < jsonArray.length(); i++) { 
       JSONObject jsonObject = jsonArray.getJSONObject(i); 
       town[i] = new ObjectTown(); 
       town[i].setId(Integer.parseInt(jsonObject.getString("id"))); 
       town[i].setName(jsonObject.getString("name")); 
       town[i].setLat(Double.parseDouble(jsonObject.getString("latitude"))); 
       town[i].setLon(Double.parseDouble(jsonObject.getString("longitude"))); 
      } 
     } catch (Exception e) { 
      Log.i("Catch the exception", e + ""); 
     } 
     return null; 
    } 

    protected void onPostExecute(Void v) {} 
} 

而且readFeed()函數在這裏:

public static String readFeed(Context context, String str) { 
    StringBuilder builder = new StringBuilder(); 
    HttpClient client = new DefaultHttpClient(); 
    HttpGet httpGet = new HttpGet(str); 

    try { 
     HttpResponse response = client.execute(httpGet); 

     StatusLine statusLine = response.getStatusLine(); 
     int statusCode = statusLine.getStatusCode(); 
     if (statusCode == 200) { 
      HttpEntity entity = response.getEntity(); 
      InputStream content = entity.getContent(); 
      BufferedReader reader = new BufferedReader(new InputStreamReader(content, "ISO-8859-1")); 
      String line; 
      while ((line = reader.readLine()) != null) { 
       builder.append(line); 
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return builder.toString(); 
} 

它的工作原理有時 ...但過一段時間,在doInBackground()拋出此異常:

org.json.JSONException:在字符的輸入0結束......

我究竟做錯了什麼?

回答

1

它看起來像服務器沒有返回數據,你檢查它,你的字符串是非空?要打開HttpEntity成字符串你可以使用:

String jsonStr = EntityUtils.toString(httpEntity); 

我想你也應該檢查,如果實體是使用它之前null不同。

+0

問題是,它只有_sometimes_拋出這個錯誤! (服務器上的文件始終可用)。 – user934779 2012-04-18 16:01:29

+1

當錯誤發生時檢查了readTown內容嗎? – marcinj 2012-04-18 16:29:23

+0

有時候,readTown的內容不會返回結果。這是問題。 – user934779 2012-04-18 17:33:38

1

使用AsyncTasks發送REST請求並不是一個好主意。 AsyncTasks不應該用於網絡等長時間運行的操作。事實上的AsyncTask有涉及兩個主要問題:

  • 他們不好綁在活動的生命週期
  • 將導致內存泄漏很容易。

裏面的RoboSpice動機應用程序(available on Google Play)我們給AsyncTasks的深度來看,裝載機,它們的特點和缺點,當涉及到網絡,也給你介紹一個替代解決方案:RoboSpice。

我們甚至提供了an infographics來解釋這個問題。把它用幾句話

  • AsyncTasks是有缺陷的,因爲它們不好綁到活動的生命週期和內存泄漏的
  • 裝載機是什麼,他們已經設計了相當不錯的:SQLite數據庫的訪問遊標,但不要爲網絡提供任何支持。他們是這個錯誤的工具。
  • RoboSpice在服務中執行網絡請求,您的下載在Android服務中執行,內存管理良好,甚至爲編寫REST請求提供支持。

我鼓勵你下載RoboSpice Motivations app,它確實說明對此進行了深入,並提供樣品和方式的不同做一些後臺操作演示。