Android使用HttpURLConnection请求网络返回JSON数据并解析
要求:
制作一个类似于今日头条的客户端,首页显示10条新闻。
思路:
使用Android的HttpURLConnection类请求一个URL,返回JSON数据,并使用自带的JSONArray类进行解析。
方法:
利用HttpURLConnection类请求网络数据(GET):
URL url = new URL(urlStr); HttpURLConnection httpconn = (HttpURLConnection) url.openConnection(); httpconn.setRequestProperty("accept", "*/*"); httpconn.setDoInput(true); httpconn.setDoOutput(true); httpconn.setConnectTimeout(5000); httpconn.connect(); int stat = httpconn.getResponseCode(); String ss = httpconn.getRequestMethod(); Log.i("Tag", "CODE:" + stat); String msg = ""; if (stat == 200) { br = new BufferedReader(new InputStreamReader(httpconn.getInputStream())); msg = br.readLine(); Log.i("Tag", "msg" + msg); Bundle b = new Bundle(); b.putString("msg", msg); Message m = new Message(); m.setData(b); handler.sendMessage(m); } else { msg = "请求失败"; }
一开始一直抛出异常,后来了解到要使用子线程:
new Thread(new Runnable() { @Override public void run() { BufferedReader br = null; try { URL url = new URL(urlStr); HttpURLConnection httpconn = (HttpURLConnection) url.openConnection(); httpconn.setRequestProperty("accept", "*/*"); httpconn.setDoInput(true); httpconn.setDoOutput(true); httpconn.setConnectTimeout(5000); httpconn.connect(); //int stat = httpconn.getResponseCode(); int stat = 200; String ss = httpconn.getRequestMethod(); Log.i("Tag", "CODE:" + stat); String msg = ""; if (stat == 200) { br = new BufferedReader(new InputStreamReader(httpconn.getInputStream())); msg = br.readLine(); Log.i("Tag", "msg" + msg); Bundle b = new Bundle(); b.putString("msg", msg); Message m = new Message(); m.setData(b); handler.sendMessage(m); } else { msg = "请求失败"; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } }).start();
并用Handler捕捉返回的Message:
final android.os.Handler handler = new android.os.Handler() { public void handleMessage(Message msg) { super.handleMessage(msg); Bundle b = msg.getData(); newsTemp = b.getString("msg"); Log.i("Tag", "handle" + b.getString("msg")); Log.i("Tag", "newsTemp" + newsTemp); initData(b.getString("msg")); } };
所以requestNews应该这样写:
public void requestNews() throws Exception { final String urlStr = getString(R.string.get_url); Log.i("Tag", "start"); final android.os.Handler handler = new android.os.Handler() { public void handleMessage(Message msg) { super.handleMessage(msg); Bundle b = msg.getData(); newsTemp = b.getString("msg"); Log.i("Tag", "handle" + b.getString("msg")); Log.i("Tag", "newsTemp" + newsTemp); initData(b.getString("msg")); } }; new Thread(new Runnable() { @Override public void run() { BufferedReader br = null; try { URL url = new URL(urlStr); HttpURLConnection httpconn = (HttpURLConnection) url.openConnection(); httpconn.setRequestProperty("accept", "*/*"); httpconn.setDoInput(true); httpconn.setDoOutput(true); httpconn.setConnectTimeout(5000); httpconn.connect(); //int stat = httpconn.getResponseCode(); int stat = 200; String ss = httpconn.getRequestMethod(); Log.i("Tag", "CODE:" + stat); String msg = ""; if (stat == 200) { br = new BufferedReader(new InputStreamReader(httpconn.getInputStream())); msg = br.readLine(); Log.i("Tag", "msg" + msg); Bundle b = new Bundle(); b.putString("msg", msg); Message m = new Message(); m.setData(b); handler.sendMessage(m); } else { msg = "请求失败"; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } }).start(); }
JSON数据格式如下:
[
{
“title”: “一双鞋子竟有这样的操作 被设计师的脑洞折服”,
“content”: “即便见过时尚界各种大胆的服饰设计,你也想不到一双鞋子竟然还有这样的操作——只有鞋底,没有鞋面!这双鞋子由意大利公司NakeFit推出,主要针对度假、休闲时的糟糕路况所设计,具有防水、耐磨、隔热、防滑等功能,携带方便,最关键是的足够拉风。目前这双鞋正在Kickstarter平台接受众筹,有黑、粉、蓝三种颜色可选,价格为33美元。怎么样,你有兴趣吗?”,
“pubDate”: “2017-06-16 09:10:12”,
“desc”: “即便见过时尚界各种大胆的服饰设计,你也想不到一双鞋子竟然还有这样的操作——只有鞋底,没有鞋面!这双鞋子由意大利公司NakeFit推出,主要针对度假、休闲时的糟糕路况所设计,具有防水、耐磨、隔热、防滑…”,
“img”: “http://upload.news.cecb2b.com/2017/0616/1497602230812.jpg”
},
{
“title”: “苹果也玩快充 新iPad可支持29W充电器”,
“content”: ” 苹果最新的10.5英寸iPad Pro已经发货,不少消费者也都陆续收到了新品,但有网友反映新款iPad Pro的充电速度较慢,但实际上,新品是支持快充的,只不过充电器需单独购买。 10.5英寸iPad Pro采用了USB 3.0 Lightning接口,理论上支持快充。微博网友肥威已经证实,使用苹果MacBook笔记本的29W充电器可为iPad Pro进行快速充电,但遗憾的是,10.5英寸iPad Pro自带的充电器仅为12W,因此要想对其进行快速充电的话需要单独购买29W的充电器。 有国外网友实测得知,使用29W充电器为10.5英寸iPad Pro进行快速充电,145分钟可以充满,但所有iOS设备在充电80%后都会进入涓流充电模式,因此前80%的数据更加重要,10.5英寸iPad Pro快充80%电量需要90分钟,还是非常不错的。提示:支持键盘“← →”键翻页 阅读全文”,
“pubDate”: “2017-06-16 08:50:09”,
“desc”: “苹果最新的10.5英寸iPadPro已经发货,不少消费者也都陆续收到了新品,但有网友反映新款iPadPro的充电速度较慢,但实际上,新品是支持快充的,只不过充电器需单独购买。微博网友肥威已经证实…”,
“img”: “http://ol01.tgbusdata.cn/v2/thumb/jpg/RTQ4Qyw1ODAsMTAwLDQsMywxLC0xLDAscms1MCwxOTIuMTY4LjguNjc=/u/iphone.tgbus.com/UploadFiles/201706/2017061613240442.jpg”
}
]
这样得到了一个String的新闻素材,接下来利用JSONArray解析JSON数据:
public void formatData(String msg) throws JSONException { newsList = new ArrayList<>(); JSONArray jsonArray = new JSONArray(msg); for(int i=0;inew News(jsonObject.getString("title"),jsonObject.getString("desc"),jsonObject.getString("img"),jsonObject.getString("content"),jsonObject.getString("pubDate"))); } }