摘要:android中使用httpclient类的get或post方法获取网络的内容,并将获取的json对象解析后设置UI。
学习自极客学院android视频,《数据存储》章中《操作JSON数据》,《网络通信》章中《异步任务》和《基于http通信》。Java学的太渣,很多专业名词还说不明白,学HttpClient是因为学习经过用到了从php后台接口接受Json数据并解析展示到程序中,学了两天总算搞明白了,写本文只为自己总结学习经过,尝试过几种方法,还是觉得这一套比较容易理解掌握。
问题多多,欢迎指正。
再鄙视下CSDN的编辑器,太TM难用了....光为了调整格式,重新编辑了十几次啊!
10.30更新:真是被CSDN编辑器坑惨了,更新了post方法,但是因为之前的代码找不到了,把例子变了,应该对java熟悉点的都能看懂,看不懂了再讨论吧。
一、创建XML文件
为了方便演示,在layout中创建一个界面,界面中一个编辑框、一个按钮、一个文本框即可,代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id ="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交" />
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="wait..." />
</LinearLayout>
二、httpclient
http协议有两种,urlconnect和httpclient,分别有get和post两种方法,这里介绍httpclient中的get方法。
HttpClient client;
client = new DefaultHttpClient();
声明HttpClient对象,urlString就是一个地址。
HttpGet get = new HttpGet(urlString);
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
String value = EntityUtils.toString(entity);
具体的原理我也说不清,总之通过这样可以将网页内容保存在value字符串里。
post方法的区别就是把参数不放在url里,而是通过设置键值对来实现
HttpPost post = new HttpPost(urlString)
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("cate", con));
post.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = client.execute(post);
String value = EntityUtils.toString(response.getEntity());
如果使用post,url里参数就只有链接了,下面的例子就是使用post实现
三、 AsyncTask异步任务
如果把上面的代码放在主线程(UI线程)中,一直会出现超时异常,因为在主线程中不允许进行长时间的操作,可以使用handler新建线程进行操作,不过比较而言,还是这个轻量级的 AsyncTask更容易理解和使用。这里使用的post方法,和上面类似。
public void readNet(String url, String con) {
new AsyncTask<String, Void, String>() {
@Override
protected String doInBackground(String... arg0) {
String urlString = arg0[0];
String con = arg0[1];
HttpPost post = new HttpPost(urlString);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("cate", con));
try {
post.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = client.execute(post);
String value = EntityUtils.toString(response.getEntity());
// System.out.println(value);
return value;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// HttpGet get = new HttpGet(urlString);
// try {
// HttpResponse response = client.execute(get);
//
// String value = EntityUtils.toString(response.getEntity());
//
// return value;
//
//
// } catch (ClientProtocolException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
return null;
}
@Override
protected void onPostExecute(String result) {
}
}.execute(url, con);
}
我把AsyncTast放在一个方法中,主线程调用这个方法即可使用这个AsyncTask
readNet(url,param1...);
这里的几个参数分别是地址,第一个参数,第二个参数....
新建AsyncTast需要设置三个参数
new AsyncTask<String, Void, String>() {
}.execute(url)
第一个代表传入的数据类型,即最后execute中的参数类型;
中间的代表若重写onPreExcute方法,使用的参数类型,如果没有,使用void;
第三个代表使用onPostExecute方法使用的数据类型,这里是String,这个方法表示异步任务执行完,执行的内容。
下面重写doInBackground这个方法
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
return null;
}
这里面就是要异步执行的代码,把httpclient要执行的内容放在里面
在捕获异常的try里面,有一个return value,这里我也不明白,只知道目的是这里的return后面的值即是,onPostExecute这个方法的参数。
最后在onPostExecute中,将result解析,然后再设置给主线程的UI。
四、解析json格式
关于Json这里不做介绍,不清楚的可以先学习一下。我们以我做应用时的解析的为例,先看看得到的value内容是什么,因为整个获取网页内容的代码是在Async中获得,所以解析Json对象并且设置UI的操作都放在onPostExecute这个方法中。
{"list":[
{"title":"\u4ef7\u683c\u6807\u9898\u5566","id":"1","author":"\u6709","time":null},{"title":"\u95c3\u630e\u67c9\u6924","id":"2","author":"\u95c3\u630e\u67c9\u6924","time":"2014-10-02 12:02:59"},{"title":"\u963f\u65af\u987f1","id":"3","author":"\u963f\u65af\u987f2","time":"2014-10-02 12:10:11"},{"title":"you","id":"5","author":"cxz","time":"2014-10-02 17:45:58"},{"title":"\u963f\u65af\u987f1","id":"7","author":"\u963f\u65af\u987f2","time":"2014-10-03 10:54:59"}
],
"hasMore":false}
JSONObject root;
try {
root = new JSONObject(result);
tv.setText(root.getJSONArray("list").toString());
JSONArray array = root.getJSONArray("list");
for (int i = 0; i < array.length(); i++) {
JSONObject lan = array.getJSONObject(i);
System.out.println("-------------");
System.out.println("title=" + lan.getString("title"));
System.out.println("id=" + lan.getInt("id"));
System.out.println("author=" + lan.getString("author"));
System.out.println("time=" + lan.getString("time"));
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
新建一个JSONObject对象root,参数就是刚才传过来的result
这时候使用root.getString("键名")可以查看query这个键里面的值
对于像含有一个数组的,先声明一个Json数组,再实例化,再通过上面的方法就可以获得每个数组的值。
总之对于{}我们可以通过JSONObject解析,[]可以通过getJSONArray解析。
想将什么内容设置到textview里,就是用tv.settext()方法就行
再次感慨:我太渣了...logcat里还是有好多看不懂的啊...