【问题标题】:Android Parse JSON stuck on get taskAndroid Parse JSON 卡在获取任务上
【发布时间】:2013-08-08 14:51:31
【问题描述】:

我正在尝试解析一些 JSON 数据。我的代码工作了一段时间,我不确定我改变了什么来突然破坏代码。当我运行我的代码时,我没有收到任何运行时错误或警告。我创建了一个新的 AsyncTask 并执行它。当我在这个新任务上调用.get() 时,调试器停在这条线上,需要 30 多分钟。我无法获得调试器或在运行期间完成此任务。

JSON:

protected void setUp(Context context) {
    _context = context;
    getConfig();
}

// get config file
protected void getConfig() { 
    if (config != null)
        return;

    config = new Config();

    String url = configURL;
    AsyncTask<String, Integer, JSONObject> jsonTask = new DownloadJSONTask()
            .execute(url);
    JSONObject configItem = null;
    try {
        configItem = jsonTask.get(); //debugger pauses here
        if (configItem == null)
            return;
        config.configVersion = configItem.getString("field_configversion");
        config.currentAppVersion = configItem
                .getString("field_currentappversion");
        config.getSupportURL = configItem.getString("field_getsupporturl");
        config.getCatalogURL = configItem.getString("field_getcatalogurl");
        config.getDataVersion = configItem.getString("field_dataversion");
        config.getDataUrl = configItem.getString("field_dataurl");
        config.getDataApiKey = configItem.getString("field_dataapikey");
    } catch (InterruptedException e) {
        e.printStackTrace();
        System.err.println("Download of config interrupted");
    } catch (ExecutionException e) {
        e.printStackTrace();
        System.err.println("Download of config failed to execute");
    } catch (JSONException e) {
        e.printStackTrace();
    } 

    cacheStaticData(_context);
}

下载JSONTask.java

package com.example.simplegraph;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.os.AsyncTask;

public class DownloadJSONTask extends AsyncTask<String, Integer, JSONObject> {
private HttpClient client = new DefaultHttpClient();
private HttpGet request;
private HttpResponse response;

DownloadJSONTask() {
    super();
}

// tries to grab the data for a JSONObject
@Override
protected JSONObject doInBackground(String... urls) {

    request = new HttpGet(urls[0]);
    try {
        response = client.execute(request);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream instream = entity.getContent();
            String result = convertStreamToString(instream);
            JSONObject json = new JSONObject(result);
            instream.close();
            return json;
        }
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return null;
}

// converts the InputStream to a string and add nl
private String convertStreamToString(InputStream is) {
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();
    String line = null;
    try {
        while ((line = br.readLine()) != null) {
            sb.append(line + "\n");
        }
    } catch (IOException ioe) {
        ioe.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    return sb.toString();
}
}

还有 HomeActivity.java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    new AddStringTask().execute();

}

class AddStringTask extends AsyncTask<Void, String, Void> {
    @Override
    protected Void doInBackground(Void... unused) {

        app = (EconApplication) getApplication();
        getApp().setUp(HomeActivity.this);
        HomeActivity.this.setUpDrawer();
        return (null);
    }

    @Override
    protected void onPostExecute(Void unused) {
        setUpDataDisplay();
        setUpGraphRange();
        createTable();
        createGraph(-1);
    }
}

问题:为什么我的代码卡在 .get() 上?

【问题讨论】:

  • "stuck" 表示哪个 logcat 输出?
  • 这个方法get()在哪里,它有什么作用?
  • @Raghunandan get() 在第一组代码中。刚试完。它用于获取 JSON。
  • @bofredo 没有 logcat 输出。除了通常的堆栈分配和释放。
  • get 从哪里你有一个方法叫做 get defined anywhere in your code?。使用接口将结果传递回活动

标签: java android json android-asynctask


【解决方案1】:

AsyncTask.get() 阻塞调用者线程。请改用AsyncTask.execute()

public final Result get ()

在 API 级别 3 中添加

如有必要,等待计算完成,然后检索 结果。

返回计算结果。

借鉴

How do I return a boolean from AsyncTask?

试试下面的

  new DownloadJSONTask(ActivityName.this).execute(url);

在你的 DownloadJSONTask 中

在构造中

    TheInterface listener;
    public DownloadJSONTask(Context context)
{

    listener = (TheInterface) context;

}

界面

   public interface TheInterface {

    public void theMethod(ArrayList<String> result); // your result type

     }

在您的doInbackground 中返回结果。我假设它的 ArrayList 类型为 String。将 arraylist 更改为适合您的要求。

在你的onPostExecute

   if (listener != null) 
   {
      listener.theMethod(result); // result is the ArrayList<String>
      // result returned in doInbackground 
      // result of doInbackground computation is a parameter to onPostExecute 
   }

在你的活动类中实现接口

 public class ActivityName implements DownloadJSONTask.TheInterface

然后

 @Override
 public void theMethod(ArrayList<String> result) { // change the type of result according yo your requirement
 // use the arraylist here
 }

编辑:替代

您可以使您的 asynctask 成为您的活动类的内部类。 doInbackground 计算的结果是 onPostExecute 的参数。在doInbackground 中返回结果。更新 onPostExecute 中的 ui。

【讨论】:

  • 再次感谢您,这很有帮助。
【解决方案2】:

您可以使用droidQuery 库大大简化一切:

$.getJSON("http://www.example.com", null, new Function() {//this will run using an AsyncTask, get the JSON, and return either a JSONObject or JSONArray on the UI Thread.
    @Overrde
    public void invoke($ droidQuery, Object... params) {
        if (params[0] instanceof JSONObject) { //it's often ok just to assume a JSONObject, making your first line simply: JSONObject obj = (JSONObject) params[0];
            //JSONObject is returned
            JSONObject json = (JSONObject) params[0];
            //to easily parse this Object, convert it to a map first:
            Map<String, ?> map = $.map(json);
            //then you can just make a call like this:
            if (map.contains("field_currentappversion")) {
                config.currentAppVersion = (String) map.get("field_currentappversion");
            }
        }
        else {
            //JSONArray is returned
            JSONArray json = (JSONArray) params[0];
            //if you got an array, you can easily convert it to an Object[] for parsing:
            Object[] array = $.makeArray(json);
        }
    }
});

【讨论】:

  • 这并不能解决我的问题,而是建议我使用其他库。
猜你喜欢
  • 2015-10-29
  • 2023-03-11
  • 1970-01-01
  • 2014-11-29
  • 1970-01-01
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多