0

我的服务器上有一个 JSON 文件(towns.json),在我的应用程序中,我希望从那里读取数据。所以我想我应该使用 AsyncTask 来不阻塞 UI 线程。我这样做如下:

    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 处输入结束...

我到底做错了什么?

4

2 回答 2

1

看起来服务器没有返回数据,你检查过你的字符串是非空的吗?要将 HttpEntity 转换为字符串,您可以使用:

String jsonStr = EntityUtils.toString(httpEntity);

我想您还应该在使用实体之前检查实体是否与 null 不同。

于 2012-04-18T15:34:59.397 回答
1

使用 AsyncTasks 发送 REST 请求不是一个好主意。AsyncTasks 不应该用于网络等长时间运行的操作。事实上 AsyncTask 有两个相关的主要问题:

  • 它们与活动生命周期的联系很差
  • 创建内存泄漏很容易。

RoboSpice Motivations 应用程序(可在 Google Play 上获得)中,我们深入了解了 AsyncTasks、Loaders、它们在网络方面的功能和缺点,并向您介绍了另一种解决方案:RoboSpice。

我们甚至提供了一个信息图表来解释这个问题。简而言之

  • AsyncTasks 是有缺陷的,因为它们与活动生命周期的联系很差并且会造成内存泄漏
  • 加载器非常适合它们的设计用途:访问 Sqlite 数据库的游标,但不提供任何网络支持。他们是错误的工具。
  • RoboSpice 在服务中执行网络请求,您的下载在 Android 服务中执行,内存管理良好,甚至还支持编写 REST 请求。

我鼓励您下载RoboSpice Motivations 应用程序,它确实深入地解释了这一点,并提供了执行某些后台操作的不同方法的示例和演示。

于 2012-10-26T07:00:05.387 回答