一.JSON基础知识
(一)什么是json
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但 是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。
(二)JSON建构于两种结构
1.“名称/值”对的集合(A collection of name/value pairs)。
不同的语言中,它被理解为对象(object),哈希表 (hash table),有键列表(keyed list),或者关联数组 (associative array)等等。
2.值的有序列表(An ordered list of values)。
在大部分语言中,它被理解为数组 (array)。
这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。
(三)JSON形式
1.对象是一个无序的“‘名称/值’对”集合。
一个对象以“{”(左括号)开始,“}”(右括 号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号) 分隔。
2.数组是值(value)的有序集合。
一个数组以“[”(左中括号)开始,“]”(右中括号)结 束。值之间使用“,”(逗号)分隔。
3.值(value)可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、 对象(object)或者数组(array)。这些结构可以嵌套。
4.几个例子
(1)例子: Array里面包含对象(object)
[ {“id”:1,”name”:”小猪” ,”age”:22} , {“id”:2,”name”:”小猫”,”age”:23} , …….]
Array里面的对象数据是有序的
(2)例子:对象(object)中可以包含Array
一个对象包含1个数组,2个子对象
{“root”:
[{“id”:”001”,”name”:”小猪”},
{“id”:”002”,”name”:”小猫”}, {“id”:”003”,”name”:”小狗”}] , “total”:3, “success”:true }
其中这里的root对应的值是数组数据,total对应的值是一个int类型数据,success对应的是一个布尔类型数据;其中root对应的值里面还有很多数据。
(3)以对象嵌套子对象,子对象再嵌套数组
{“calendar”:
{“calendarlist”:
[{“id”:”001”,”name”:”小猪”}, {“id”:”002”,”name”:”小猫”}]
}
}
这里的数据最外层只有一个键值对:calendar对应对象value1,value1里面也是只有一个键值对:calendarlist对应数组数据ArrayValue,ArrayValue里面又两个有序对象,这两个有序对象里面都有两个无序的数据。
(四)Android中JSON类
在Android中包含四个与JSON相关的类和一个Exceptions:分別是 JSONArray、JSONObject、 JSONStringer、JSONTokener、JSONException;下面分別进行介绍:
(1)JSONObject:
这是系统中有关JSON定义的基本单元,其包含一对儿(Key/Value)数值。
它对外部(External:应用toString()方法输出的数值)调用的响应体现为一个标准的字符串(例 如:{“JSON”: “Hello, World”},最外被大括号包裹,其中的Key和Value被冒号”:”分 隔)。其对于内部(Internal)行为的操作格式略微,例如:初始化一个JSONObject实例,引用 内部的put()方法添加数值:new JSONObject().put(“JSON”, “Hello, World!”),在Key 和Value之间是以逗号”,”分隔。
Value的类型包括:Boolean、JSONArray、JSONObject、Number、String或者默认值 JSONObject.NULL object。
有两个不同的取值方法: get(): 在确定数值存在的条件下使用,否则当无法检索到相关Key时,将会抛出一个Exception 信息。 opt(): 这个方法相对比较灵活,当无法获取所指定数值时,将会返回一个默认数值,并不会抛出异常。所以我们使用opt的方法来取值。
(2)JSONArray: 它代表一组有序的数值。
将其转换为String输出(toString)所表现的形式是用方括号包裹,数值以逗号”,”分隔(例如:[value1,value2,value3],大家可以亲自利用简短的代码更加直观的了解其格式)。这个类的内部同样具有查询行为,get()和opt()两种方法都可以通过index索 引返回指定的数值,put()方法用来添加或者替换数值。同样这个类的value类型可以包括:Boolean、JSONArray、JSONObject、Number、String 或者默认值JSONObject.NULL object。
(3)JSONStringer:
根据官方的解释,这个类可以帮助快速和便捷的创建JSONtext。其最大的优点在于可以减少 由于格式的错误导致程序异常,引用这个类可以自动严格按照JSON语法规则(syntaxrules) 创建JSONtext。每个JSONStringer实体只能对应创建一个JSONtext。
(4)JSONTokener:
这个是系统为JSONObject和JSONArray构造器解析JSON source string的类,它可以从
source string中提取数值信息。
(5)JSONException:
是JSON.org类抛出的异常信息。
在JSON数据解析中,常用的两个类就是JSONObject和
JSONArray;
二.JSON解析数据的一个简单示例演示
(一)比如从网络中获取到下面的一段字符串,需要去解析到每一个动物的姓名和它的图片URL网址
S=”{"root":
[{"id":"001","name":"小猪",“img”:”StringURL1”},
{"id":"002","name":"小猫",“img”:”StringURL2”}, {"id":"003","name":"小狗",“img”:”StringURL3”}]
, "total":3, "success":true }”
(二)解析过程的语句
创建两个数组用来存储数据
String[] names=new String[3];
String[] imgURLs=new String[3];
//数据的获取过程
JSONObject jsonObject = new JSONObject(s)
JSONArray array =jsonObject.optJSONArray("root");//获得json数组,数组里面有三个对象
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.optJSONObject(i);//数组数据是根据游标值获取
names[i]=obj.optString(“name”);//获取名字
imgURLs[i]=obj.optString(“img”);//获取图片的URL
}
到这里上面的两个存放数据的数组已经有数据了。
这里只是简单的示范,实际中的网络数据都是有几百行代码或更多,但是取数据的方式还是一样的。
三.解析网络中复杂的json数据的程序示例
这里设计一个简易的笑话大全的软件。
程序运行后显示的界面:
这里的布局设计的是两个按钮,单击“java请求”获取的是页面源码的json数据;
点击“Android请求笑话大全”,跳转到另一个页面显示解析后的数据,并且点击前还可以对笑话的数据进行选择,如选择页码或选择查看笑话的图片。。。
(一)数据请求的准备和分析
这里使用的网络中请求的数据,相当于一个完整的app的数据。
这里推荐一个请求json数据的一个网站:ShowAPI
里面可以获取很多使用的数据,比如天气预报,快递查询,附近景点,公交车信息查询等等。其实里面提供的都是对应的链接的URL字符串,但是这里都帮我们整理好相关的数据了,我们只需要调用它提供的API就可以实现对应的功能。
要获得网站的数据要先进行注册,这里注册是非常简单的。
注册成功后,点击右上角–个人中心,选择–我的应用,至少要确保自己又一个app名称,如果没有就去添加,这里的appid和secret对应的值是我们链接网址必须要用到的。
注册成功后搜索要查找的数据的API,如图所示:
右上角点击订阅,做相关操作后才能显示可调用。
点击进去可以查看使用方法和其他的相关介绍,比如可以显示很多的笑话文本/笑话图片/动态图片;
上面的URL并不是完整的URL,还需要添加它规定的参数才能使用,那么就要查看它是怎么规定参数的。。。
查看请求的参数要求中可以看到,有些数据是必须要的添加才能在URL中请求到数据的;
比如上面的数据中showapi_appid和showapi_sign是必须要的,这个也是我们注册后才有的数据值。
其他的数据也可以做简单的了解,比如page代表的是你要请求的是第几页,如果没有输入,默认是1;
根据网站的提示,我们可以得到一个简单的URL字符串地址path=”http://route.showapi.com/341-1?showapi_appid=27155&page=&showapi_sign=5bd3b5774c2346068463b526171ba86e”
这里的属相的值用冒号:对应,每一对值使用&号隔开,还要记得在基础的URL后面加一个?号。
请求到的数据是一大串的json格式的字符串;
对于这个返回的字符串我们也是要去看一下的,因为我们的json解析是从外到内一层一层去解析数据的。这里最好下载一个json数据格式化的工具,或者在网页中直接使用json格式化工具,可以把一长串的字符串显示为json格式,方便我们去解析它的数据。
数据解析前,如图所示:
数据显示的是连接在一起的,很难区分标签和段落所以使用解析工具就非常重要了。
数据解析后,如图所示:
可以很清楚的看到我们要取的数据的关键字。
这里提供一个代码解析工具的下载的网址:
http://download.csdn.net/detail/wenzhi20102321/9684426
网站提示,数据解析后,返回需要的数据。
上面是通过json解析后可以得到的很多数据,但是实际中我们只需要提取一些需要的数据就可以了。
(二)程序的实际设计
1.布局文件activity_main.xml的设计
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="conn1"
android:text="java请求" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/main_et_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_weight="1"
android:background="@null"
android:hint="输入页数"
android:singleLine="true" />
<CheckBox
android:id="@+id/main_cb_isImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选择图片" />
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="conn2"
android:text="Android请求笑话大全" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/main_tv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ScrollView>
</LinearLayout>
上面使用一个ScrollView来显示获取到的json数据。
2.布局文件activity_joke.xml文件的设计
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/joke_tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="title"
android:textColor="@android:color/black"
android:textSize="18sp" />
<TextView
android:id="@+id/joke_tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="content"
android:textColor="@android:color/black"
android:textSize="16sp" />
<ImageView
android:id="@+id/joke_iv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:adjustViewBounds="true"
android:scaleType="fitXY" />
<TextView
android:id="@+id/joke_tv_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="right"
android:text="时间"
android:textSize="14sp" />
</LinearLayout>
上面的布局是每一个笑话内容显示的布局设计。
3.创建一个json解析和数据收集的类
package com.lwz.conn;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.Serializable;
import java.util.ArrayList;
/**
* 这是一个数据解析的工具类,
* <p>
* 这里是从源码中取出属性值
* 这里是使用从外到内一层一层的去获取资源数据,最里面一层的数据才是我们要显示在页面上的数据
* 这里的处理的方式是比较麻烦的一种,其中它处理的方式可以有好几种
* 这里的数据层层嵌套,就像xml资源的子标签一样
*/
/*下面是提供API网站给我们的数据的提示,xml文件中下面的某些变量,我们可以选择性的去使用,
但是这些变量的名字是固定的,更改了就获取不到了
allNum String 345 所有记录数
allPages String 45 所有页数。每页20条。
contentlist JokeItem[] 笑话条目内容
- title String 吃了一百年的玉米 笑话标题
- text String 笑话正文
- ct String 2015-07-10 05:54:00.000 生成时间
currentPage String 1 当前第几页
maxResult String 20 每页最多显示几条*/
//因为要Intent来实现数据的传递,所以要实现序列化
public class JokeBean implements Serializable {
//最外层的属性值
int showapi_res_code;
String showapi_res_error;
Body showapi_res_body;//这个才是有用的信息数据,上面的实现其实也是可以不用去定义的
@Override
public String toString() {
return "JokeBean{" +
"showapi_res_body=" + showapi_res_body +
", showapi_res_code=" + showapi_res_code +
", showapi_res_error='" + showapi_res_error + '\'' +
'}';
}
class Body implements Serializable {
int allNum;
int allPages;
int currentPage;//当前第几页
int maxResult;
int ret_code;
ArrayList<Content> contentlist;
@Override
public String toString() {
return "Body{" +
"allNum=" + allNum +
", allPages=" + allPages +
", currentPage=" + currentPage +
", maxResult=" + maxResult +
", ret_code=" + ret_code +
", contentlist=" + contentlist +
'}';
}
class Content implements Serializable {
String id;
String ct;//生成时间
String text;//笑话正文
String title;//笑话标题
int type;//文本笑话,图片笑话,动态图笑话
String img;//笑话的图片连接地址URL
//重写toString方法,查看数据
@Override
public String toString() {
return "Content{" +
"ct='" + ct + '\'' +
", id='" + id + '\'' +
", text='" + text + '\'' +
", title='" + title + '\'' +
", type=" + type +
", img='" + img + '\'' +
'}';
}
}
}
/**
* 创建一个静态的转换方法
* 将字符串使用json解析的方式,转换成对象
* 用于把资源代码的字符串中某些值赋值给某些需要的变量
*/
public static JokeBean getBeanValue(String json) {
try {
//1.将最外层的字符串,转换为json对象
JSONObject jsonObject = new JSONObject(json);
//2.创建返回的对象
JokeBean jokeBean = new JokeBean();
//3.取外层的数据,两种方法opt和get,其中opt更好,get在数据不匹配时会报错
jokeBean.showapi_res_code = jsonObject.optInt("showapi_res_code");
jokeBean.showapi_res_error = jsonObject.optString("showapi_res_error");
//4.取第二层数据,是一个对象
JSONObject bodyObject = jsonObject.optJSONObject("showapi_res_body");
//5.通过这个对象的值,再去取数据
//创建内部对象,把获取到的数据赋值给这个类的对象
Body body = jokeBean.new Body();
body.allNum = bodyObject.optInt("allNum");
body.allPages = bodyObject.optInt("allPages");
body.currentPage = bodyObject.optInt("currentPage");
body.maxResult = bodyObject.optInt("maxResult");
body.ret_code = bodyObject.optInt("ret_code");
//Log.e("TAG", "jokeBean------------>" + jokeBean.toString());
// Log.e("TAG", "body------------>" + body.toString());
//这里的contentlist的数据是数组类型的!
JSONArray array = bodyObject.optJSONArray("contentlist");
//创建一个集合用来存放数组
body.contentlist = new ArrayList<>();
//通过数据遍历循环去取所有的对象
for (int i = 0; i < array.length(); i++) {
Body.Content content = body.new Content();
//再次使用json解析数据
//集合通过optXXX(index)的方法去取值
JSONObject obj = array.optJSONObject(i);
content.ct = obj.optString("ct");//笑话的创建时间
content.id = obj.optString("id");//笑话的id编号
content.title = obj.optString("title");//笑话的标题
content.type = obj.optInt("type");//笑话的类别,1代表文本,2代表图像
//对类别的判断
if (content.type == 2) {
content.img = obj.optString("img");
} else {
content.text = obj.optString("text");
}
body.contentlist.add(content);
}
//Log.e("TAG", "body.c------------>" + body.contentlist.toString());
jokeBean.showapi_res_body = body;
//返回一个JokeBean对象,里面包含所有的数据
return jokeBean;
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
4.创建一个异步任务类,用来下载json数据
package com.lwz.conn.utils;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;
import com.lwz.conn.JokeBean;
import com.lwz.conn.ShowActivity;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 异步任务的创建
* 这里的任务是下载网络的资源文件
*/
public class MyAsyncTask extends AsyncTask<String, Void, String> {
Context context;
public MyAsyncTask(Context context) {
this.context = context;
}
//在子线程中做资源的下载
@Override
protected String doInBackground(String... params) {
try {
//从params中获取传过来的URL
URL url = new URL(params[0]);
Log.e("TAG", params[0]);
//使用URLconnection的子类HttpURLconnection来请求连接更好
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);//设置要读取文件
conn.setConnectTimeout(10000);//设置连接的最长时间
InputStream is = conn.getInputStream();//获取连接的输入流
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //创建一个高速的输出流来读取输入流
//对数据的读取(边读边取)
int len = 0;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
baos.write(buf, 0, len);
}
//获得的输出流变成String类型的字符串,用于最后的返回
String result = new String(baos.toByteArray(), "utf-8");//设置编码格式
//返回的是获取的一大串文本资源源码
Log.e("TAG","-------------->"+ result);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//任务完成后页面的跳转,把相关数据带到要跳转的页面
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//这里接收的s,就是从网络中获取到的一大串字符串的文件源码
//这里要使用json解析,从源码中来获取我们需要的数据
Log.e("TAG", s);
JokeBean jokeBean = JokeBean.getBeanValue(s);
//页面的跳转
Intent intent = new Intent(context, ShowActivity.class);
intent.putExtra("jokeBean", jokeBean); //数据传递
context.startActivity(intent);//开始跳转
}
}
5.创建一个绑定视图和URL的工具类
package com.lwz.conn.utils;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;
import com.lwz.conn.JokeBean;
import com.lwz.conn.ShowActivity;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 异步任务的创建
* 这里的任务是下载网络的资源文件
*/
public class MyAsyncTask extends AsyncTask<String, Void, String> {
Context context;
public MyAsyncTask(Context context) {
this.context = context;
}
//在子线程中做资源的下载
@Override
protected String doInBackground(String... params) {
try {
//从params中获取传过来的URL
URL url = new URL(params[0]);
Log.e("TAG", params[0]);
//使用URLconnection的子类HttpURLconnection来请求连接更好
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);//设置要读取文件
conn.setConnectTimeout(10000);//设置连接的最长时间
InputStream is = conn.getInputStream();//获取连接的输入流
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //创建一个高速的输出流来读取输入流
//对数据的读取(边读边取)
int len = 0;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
baos.write(buf, 0, len);
}
//获得的输出流变成String类型的字符串,用于最后的返回
String result = new String(baos.toByteArray(), "utf-8");//设置编码格式
//返回的是获取的一大串文本资源源码
Log.e("TAG","-------------->"+ result);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//任务完成后页面的跳转,把相关数据带到要跳转的页面
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//这里接收的s,就是从网络中获取到的一大串字符串的文件源码
//这里要使用json解析,从源码中来获取我们需要的数据
Log.e("TAG", s);
JokeBean jokeBean = JokeBean.getBeanValue(s);
//页面的跳转
Intent intent = new Intent(context, ShowActivity.class);
intent.putExtra("jokeBean", jokeBean); //数据传递
context.startActivity(intent);//开始跳转
}
}
6.创建一个BaseAdapter的工具类
package com.lwz.conn.utils;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;
import com.lwz.conn.JokeBean;
import com.lwz.conn.ShowActivity;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 异步任务的创建
* 这里的任务是下载网络的资源文件
*/
public class MyAsyncTask extends AsyncTask<String, Void, String> {
Context context;
public MyAsyncTask(Context context) {
this.context = context;
}
//在子线程中做资源的下载
@Override
protected String doInBackground(String... params) {
try {
//从params中获取传过来的URL
URL url = new URL(params[0]);
Log.e("TAG", params[0]);
//使用URLconnection的子类HttpURLconnection来请求连接更好
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);//设置要读取文件
conn.setConnectTimeout(10000);//设置连接的最长时间
InputStream is = conn.getInputStream();//获取连接的输入流
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //创建一个高速的输出流来读取输入流
//对数据的读取(边读边取)
int len = 0;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
baos.write(buf, 0, len);
}
//获得的输出流变成String类型的字符串,用于最后的返回
String result = new String(baos.toByteArray(), "utf-8");//设置编码格式
//返回的是获取的一大串文本资源源码
Log.e("TAG","-------------->"+ result);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//任务完成后页面的跳转,把相关数据带到要跳转的页面
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//这里接收的s,就是从网络中获取到的一大串字符串的文件源码
//这里要使用json解析,从源码中来获取我们需要的数据
Log.e("TAG", s);
JokeBean jokeBean = JokeBean.getBeanValue(s);
//页面的跳转
Intent intent = new Intent(context, ShowActivity.class);
intent.putExtra("jokeBean", jokeBean); //数据传递
context.startActivity(intent);//开始跳转
}
}
7.设计MainActivity.java文件
package com.lwz.conn;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.lwz.conn.utils.MyAsyncTask;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
/***
* Android网络请求示例
*/
public class MainActivity extends AppCompatActivity {
//定义布局内的控件
TextView textView;
CheckBox checkBox;
EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化控件
textView = (TextView) findViewById(R.id.main_tv);
checkBox = (CheckBox) findViewById(R.id.main_cb_isImage);
editText = (EditText) findViewById(R.id.main_et_pager);
}
//第一个按钮的回调方法
//这里请求的数页面数据的源码资源
public void conn1(View v) {
//所有的网络资源请求都是子线程中进行的
new Thread(new Runnable() {
@Override
public void run() {
//资源下载的实际代码
try {
//设置URL
URL url = new URL("http://route.showapi.com/341-1?showapi_appid=27155&time=&page=&maxResult=&showapi_sign=5bd3b5774c2346068463b526171ba86e");
// URL url = new URL("https://www.baidu.com");
//打开连接使用openConnection方法
URLConnection conn = url.openConnection();
//必须要对连接对象做相关的设置
conn.setConnectTimeout(10000);//设置连接的最长时间
conn.setDoOutput(true);//用于设置是否从连接中读取数据,如果参数值为true时,表示读取数据,否则不读取数据
//这里写数据使用setDoInput(boolean newValue),我也是感觉比较奇怪的地方!
//获取输入流
InputStream is = conn.getInputStream();
//对流里面的数据进行读取
int len = 0;
byte[] buf = new byte[1024];
final StringBuilder sb = new StringBuilder();
while ((len = is.read(buf)) != -1) {
sb.append(new String(buf, 0, len));
}
is.close();//关闭流
//把获取的字符串数据显示在UI文本中,但是要在主线程中进行
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(sb.toString());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
//连接并处理网络文件,用自定义的布局显示出来
public void conn2(View view) {
//get请求使用?来拼接参数,多个参数使用&符号
//判断是显示图片还是显示文本信息
boolean isImage = checkBox.isChecked();
//确定URL的链接地址
// 这里的showapi_appid和showapi_sign都要自己上网注册使用自己的账号的应用信息。
String baseURL = "";
if (isImage) {
baseURL = "http://route.showapi.com/341-2?showapi_appid=27155&showapi_sign=5bd3b5774c2346068463b526171ba86e&page=";
} else {
baseURL = "http://route.showapi.com/341-1?showapi_appid=27155&showapi_sign=5bd3b5774c2346068463b526171ba86e&page=";
}
int pageNum = 1;//定义more的页码数
String pageString = editText.getText().toString(); //获取用户输入页数
try {
pageNum = Integer.parseInt(TextUtils.isEmpty(pageString) ? "1" : pageString);
if (pageNum <= 1) {
pageNum = 1;
}
} catch (Exception e) {
Toast.makeText(this, "你输入的页码数有误!", Toast.LENGTH_SHORT).show();
}
baseURL += pageNum;
//使用异步任务来加载数据,在异步任务里面,任务完成后做页面跳转
MyAsyncTask task = new MyAsyncTask(MainActivity.this);
task.execute(baseURL);
}
}
8.设计另一个显示笑话的显示类
package com.lwz.conn;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.lwz.conn.utils.ImagsUtils;
/**
* 显示网络的文字或图片的页面
*/
public class ShowActivity extends Activity {
JokeBean jokeBean;//定义一个JokeBean对象
ListView listView;//定义一个ListView显示页面数据
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listView = new ListView(this);
setContentView(listView);
//获取传递过来的数据
jokeBean = (JokeBean) getIntent().getSerializableExtra("jokeBean");
//使用java代码创建一个ListView
listView.setAdapter(adapter);
}
BaseAdapter adapter = new BaseAdapter() {
@Override
public int getCount() {
return jokeBean.showapi_res_body.contentlist.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(getBaseContext(), R.layout.activity_joke, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
JokeBean.Body.Content content = jokeBean.showapi_res_body.contentlist.get(position);
if (content.type == 1) {
holder.tv_content.setVisibility(View.VISIBLE);
holder.iv_content.setVisibility(View.GONE);
holder.tv_content.setText(content.text);
} else {
holder.iv_content.setVisibility(View.VISIBLE);
holder.tv_content.setVisibility(View.GONE);
ImagsUtils.bindView(content.img, holder.iv_content);
}
holder.tv_title.setText(content.title);
holder.tv_time.setText(content.ct);
return convertView;
}
class ViewHolder {
TextView tv_title, tv_content, tv_time;
ImageView iv_content;
public ViewHolder(View convertView) {
tv_title = (TextView) convertView.findViewById(R.id.joke_tv_title);
tv_content = (TextView) convertView.findViewById(R.id.joke_tv_content);
tv_time = (TextView) convertView.findViewById(R.id.joke_tv_time);
iv_content = (ImageView) convertView.findViewById(R.id.joke_iv_content);
}
}
};
}
设计完上面的代码后,还记得要添加上网的个人权限,才能去请求网络。运行程序。
这里程序设计过程可能会遇到许多的问题,但是只要你细心,一步一步的去排查,看看问题出在哪里,这里涉及到很多字符串的变量,如果写错了经常会有的。比如出现了问题,首先要查看是否收到了json数据,在查看每一层接收到的json对象是否都有值。。。