【问题标题】:Return JSON data after async task android异步任务android后返回JSON数据
【发布时间】:2016-11-07 07:08:38
【问题描述】:

我们正在服务器上进行大量(所有必要的)调用以获取用户数据,为此我们创建了一个公共类来发布数据,并将响应作为 JSON 对象检索。但是这样我们的应用程序变得太慢了,所以我们在想,我们可以通过异步任务检索数据。

所以我们修改了如下代码:-

UserFunction.java

public JSONObject getUserData(String userName,String pNumber){
    // Building Parameters
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("tag", getUser));
    params.add(new BasicNameValuePair("search_number_array", userName));
    params.add(new BasicNameValuePair("pNumber", pNumber));
    params.add(new BasicNameValuePair("id", pNumber));
    // getting JSON Object
    JSONParser jsonParser1=new JSONParser(loginURL, params);
  // jsonParser1.getJSONFromUrl(loginURL, params);
    jsonParser1.execute();
    Jsonresult j1=new Jsonresult();
    JSONObject json =j1.getjObjResult();
            Log.d("Response:", json.toString());   //line 45, on which getting error
    return json;
} 

JSONParse.java

 public class JSONParser extends AsyncTask<String, String, JSONObject> {

static InputStream is = null;
static JSONObject jObj = null;
Jsonresult obj;
static String json = "";
List<NameValuePair> postparams= new ArrayList<NameValuePair>();
String URL=null;
// constructor
public JSONParser(String url, List<NameValuePair> params) {
    URL=url;
    postparams=params;
    Log.e("entered constructor", "entered in constructor ");

    // Making HTTP request


}

@Override
protected JSONObject doInBackground(String... strings) {
    Log.e("entered in bg", "entered in doinbackground ");

    try {
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(URL);
        httpPost.setEntity(new UrlEncodedFormEntity(postparams));

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "iso-8859-1"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
        Log.e("JSON", json);
    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    // try parse the string to a JSON object
    try {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

    // return JSON String
    return jObj;
}

public void getJSONFromUrl(String url, List<NameValuePair> params) {
    URL=url;
    postparams=params;
    Log.e("entered ", "entered in getjsonurl ");

    // Making HTTP request


}
@Override
protected void onPostExecute(JSONObject result) {
    this.obj.setjObjResult(result);
}
@Override
protected void onPreExecute() {
    // TODO Auto-generated method stub
    super.onPreExecute();
}
 }

Jsonresult.java

public class Jsonresult {
 JSONObject jObjResult = null;

public JSONObject getjObjResult() {
    return jObjResult;
}

public void setjObjResult(JSONObject jObjResult) {
    this.jObjResult = jObjResult;
}
}

但是我们遇到了这个错误

   java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.json.JSONObject.toString()' on a null object reference
        at com.keepAeye.gps.UserFunctions.getUserData(UserFunctions.java:45)

表示控制在完成后台进程之前进行。 请告诉我们如何解决这个问题?

【问题讨论】:

  • UserFunctions.java 中的第 45 行在哪里?
  • 抱歉,问题已更新。顺便说一句,这是出现错误 Log.d("Response:", json.toString());
  • 问题是你在这里创建新对象 JSONObject json =j1.getjObjResult(); ..您无需创建新对象,而是使用已在 onPostExc 中的 Aysnc 中实例化的旧对象
  • 好的。我将代码更改为此 JSONObject json =jsonParser1.obj.getjObjResult(); , 但仍然出现同样的错误。
  • 由于 AsyncTask 是后台进程,UI 线程不会等待 Async 完成。这意味着当你调用 jsonParser1.execute();然后它不会等待异步完成,您的代码将转到下一行,即 jsonParser1.obj.getjObjResult();并发现 jsonParser1.obj 为 null。

标签: java android json android-asynctask


【解决方案1】:

当你打电话时

jsonParser1.execute();

异步任务发生在另一个线程中。这意味着这些行

Jsonresult j1=new Jsonresult();
JSONObject json =j1.getjObjResult();
Log.d("Response:", json.toString());
return json;

在 JSONParser 的 doInBackground 执行之前执行(实际上它们都是并行运行的)。

这意味着当你调用j1.getjObjResult();你的代码时

@Override
protected void onPostExecute(JSONObject result) {
    this.obj.setjObjResult(result);
}

甚至还没有执行。解决这个问题的简单方法是使用类似的接口。

public interface CallBack {
    void onSuccess(JSONObject json);
}

然后在你的 UserFunction 类链接中实现这个

class UserFunction implements CallBack {
   ...
   @Override
   public void onSuccess(JSONObject json) {
     Log.d("Response:", json.toString());
   }
}

当您执行 AsyncTask 时,像这样传递回调的引用

JSONParser jsonParser1=new JSONParser(loginURL, params, this);

并在您的 AsyncTask 中维护回调的引用,例如

CallBack mCallback;

public JSONParser(String url, List<NameValuePair> params, CallBack callBack) {
    URL=url;
    postparams=params;
    mCallback = callBack;        
    Log.e("entered constructor", "entered in constructor ");

    // Making HTTP request


}

在 AsyncTask 的 onPostExecute 中执行此操作。

@Override
protected void onPostExecute(JSONObject result) {
   mCallback.onSuccess(result);
}

而且你真的应该考虑使用网络库来进行网络调用,例如 retrofitvolley

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 2014-10-01
    • 2016-08-27
    相关资源
    最近更新 更多