为 AsyncTask 实现一个常规的 JSON 解析器函数
Posted
技术标签:
【中文标题】为 AsyncTask 实现一个常规的 JSON 解析器函数【英文标题】:Implementing a regular JSON parser function to AsyncTask 【发布时间】:2019-01-15 08:35:30 【问题描述】:我正在开发一个应用程序,它有很多远程 JSON 调用来获取数据并在应用程序中实现。
目前,我正在使用此函数从 URL 获取 JSON 数据并对其进行解析。
但不幸的是,它会冻结应用程序,直到下载 JSON 文件。
google了一下,发现AsyncTask可以解决这个问题。
我刚开始开发 android 应用程序。我试过但失败了。
你们能帮我实现这个功能到 AsyncTask 吗?
public class JSONParser
String charset = "UTF-8";
HttpURLConnection conn;
DataOutputStream wr;
StringBuilder result;
URL urlObj;
JSONObject jObj = null;
JSONArray jAry = null;
StringBuilder sbParams;
String paramsString;
public JSONObject makeHttpRequest(String url, String method, HashMap<String, String> params)
sbParams = new StringBuilder();
int i = 0;
for (String key : params.keySet())
try
if (i != 0)
sbParams.append("&");
sbParams.append(key).append("=")
.append(URLEncoder.encode(params.get(key), charset));
catch (UnsupportedEncodingException e)
e.printStackTrace();
i++;
if (method.equals("POST"))
try
urlObj = new URL(url);
conn = (HttpURLConnection) urlObj.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept-Charset", charset);
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.connect();
paramsString = sbParams.toString();
wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(paramsString);
wr.flush();
wr.close();
catch (IOException e)
e.printStackTrace();
else if (method.equals("GET"))
if (sbParams.length() != 0)
url += "?" + sbParams.toString();
Log.d("URL",url);
try
urlObj = new URL(url);
conn = (HttpURLConnection) urlObj.openConnection();
conn.setDoOutput(false);
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept-Charset", charset);
conn.setConnectTimeout(15000);
conn.connect();
catch (IOException e)
e.printStackTrace();
try
InputStream in = new BufferedInputStream(conn.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null)
result.append(line);
Log.d("JSON Parser", "result: " + result.toString());
catch (IOException e)
e.printStackTrace();
conn.disconnect();
try
jObj = new JSONObject(result.toString());
catch (JSONException e)
Log.e("JSON Parser", "Error parsing data " + e.toString());
return jObj;
这是我进行 json 调用的方式:
JSONParser jsonParser = new JSONParser();
JSONObject json = jsonParser.makeHttpRequest("https://url", "GET", parametters);
【问题讨论】:
所以如果你调用 apis ,它会给你 json 响应,那么我建议你使用okhttp
或 retrofit
网络库。
这不在问题范围内。但谦虚地建议您使用网络客户端可能是 RetroFit
和 GSON
。这样你就不用解析大量的数据和更少的代码了。
【参考方案1】:
如果您想使用 AsyncTask
来做到这一点,这是一个好的开始:
public class JsonParser extends AsyncTask<Void, Void, JSONObject>
public interface ParserListener
void onSuccess(JSONObject result);
void onFailure();
private ParserListener listener;
private HashMap<String, String> params;
private String method;
private String url;
String charset = "UTF-8";
HttpURLConnection conn;
DataOutputStream wr;
StringBuilder result;
URL urlObj;
JSONObject jObj = null;
JSONArray jAry = null;
StringBuilder sbParams;
String paramsString;
public JsonParser(String url, String method, HashMap<String, String> params)
this.url = url;
this.method = method;
this.params = params;
public void setListener(ParserListener listener)
this.listener = listener;
@Override
protected JSONObject doInBackground(Void... voids)
sbParams = new StringBuilder();
int i = 0;
for (String key : params.keySet())
try
if (i != 0)
sbParams.append("&");
sbParams.append(key).append("=")
.append(URLEncoder.encode(params.get(key), charset));
catch (UnsupportedEncodingException e)
e.printStackTrace();
i++;
if (method.equals("POST"))
try
urlObj = new URL(url);
conn = (HttpURLConnection) urlObj.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept-Charset", charset);
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.connect();
paramsString = sbParams.toString();
wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(paramsString);
wr.flush();
wr.close();
catch (IOException e)
e.printStackTrace();
else if (method.equals("GET"))
if (sbParams.length() != 0)
url += "?" + sbParams.toString();
Log.d("URL",url);
try
urlObj = new URL(url);
conn = (HttpURLConnection) urlObj.openConnection();
conn.setDoOutput(false);
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept-Charset", charset);
conn.setConnectTimeout(15000);
conn.connect();
catch (IOException e)
e.printStackTrace();
try
InputStream in = new BufferedInputStream(conn.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null)
result.append(line);
Log.d("JSON Parser", "result: " + result.toString());
catch (IOException e)
e.printStackTrace();
conn.disconnect();
try
jObj = new JSONObject(result.toString());
catch (JSONException e)
Log.e("JSON Parser", "Error parsing data " + e.toString());
return jObj;
@Override
protected void onPostExecute(JSONObject jsonObject)
/* executed on main thread */
if (listener != null)
if (jsonObject != null)
listener.onSuccess(jsonObject);
else
listener.onFailure();
并使用它:
JsonParser parser = new JsonParser("https://url", "GET", parameters);
parser.setListener(new JsonParser.ParserListener()
@Override
public void onSuccess(JSONObject result)
/* delivered result */
@Override
public void onFailure()
/* delivered failure */
);
parser.execute();
代码可以改进,正如 cmets 中所指出的,有更好的方法可以做到这一点。 AsyncTask
在学习阶段仍然很有趣。
【讨论】:
嗨,非常感谢,这就是我要找的。但是要获得返回值呢? JSONParser jsonParser = new JSONParser("url", "GET", 参数);那么如何获取JSONObject呢? 响应是通过 JsonParser.ParserListener 的onSuccess
回调给出的。有意义吗?
太棒了,正是我想要的。非常感谢先生。你刚刚拯救了我的一天。希望它也能帮助其他人。以上是关于为 AsyncTask 实现一个常规的 JSON 解析器函数的主要内容,如果未能解决你的问题,请参考以下文章
AsyncTask #3 解析 JSON 对象时出错。字符串无法转换为 JSONObject
解析JSON对象的AsyncTask#3错误。 String无法转换为JSONObject
实现 Widget Android Studio 的问题 - AsyncTask