一、原生数据解析
1.要完成的效果
如下图所示,点击按钮跳转到另一个Activity,从服务器请求数据并在页面中在预定位置显示出来。
2.网络数据接口和数据结构及内容
url地址:http://www.imooc.com/api/teacher?type=3&cid=1
数据如下:
{
"status": 1,
"data": {
"title": "Tony老师聊shell——环境变量配置文件作者",
"author": "Tony",
"content": "本课程是《Tony老师聊shell》系列课程的第三篇,为你带来常用的环境变量配置文件的使用。"
},
"msg": "成功"
}
3.新建项目
1.新建一个名为HttpDemo
的项目,activity_main.xml
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingRight="15dp"
android:text="网络操作与数据解析" />
</LinearLayout>
对应的MainActivity.java
的代码为:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_net).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//点击按钮后页面跳转
startActivity(new Intent(MainActivity.this, DetailActivity.class));
}
});
}
}
2.在Android Studio中单击菜单栏File-->New-->Activity-->EmptyActivity
,Activity名为DetailActivity
,Layout名为activity_detail
。activity_detail.xml
代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content_detail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".DetailActivity"
tools:showIn="@layout/activity_detail">
<TextView
android:id="@+id/titlename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:gravity="center"
android:textSize="24sp" />
<TextView
android:id="@+id/author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:gravity="right"
android:paddingRight="10dp"
android:textSize="20sp" />
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:layout_marginTop="15dp"
android:layout_weight="1"
android:lineSpacingMultiplier="1.5"
android:textSize="20sp" />
</LinearLayout>
4.网络请求及数据解析
首先来分析一下步骤,使用HttpUrlConnection去做网络请求及数据解析主要分为以下4个步骤:
1. 实例化一个url对象【参数:你要访问的接口地址】
2. 获取HttpUrlConnection对象
3. 设置请求连接属性
4. 获取响应吗,判断是否连接成功,若连接成功,则读取输入流并解析
要注意的有:访问网络的操作不能在UI线程中进行,需开辟新线程来操作,并且要借助Handler来完成线程间的通信(UI线程与开辟的用于网络请求及数据解析的线程),并且还要新建一个Essay类进行线程间信息的传输。
Essay.java代码如下(对应了详情页DetailActivity页面的三项内容):
public class Essay {
private String title;
private String author;
private String content;
public Essay(String title, String author, String content) {
this.title = title;
this.author = author;
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
网络请求及数据解析主要在详情页进行,详情页面DetailActivity.java
代码如下:
public class DetailActivity extends AppCompatActivity {
private TextView titleTextView, authorTextView, contentTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
initView();
initData();
}
private void initView() {
titleTextView = findViewById(R.id.titlename);
authorTextView = findViewById(R.id.author);
contentTextView = findViewById(R.id.content);
}
private void initData() {
/*开辟一个新线程*/
new Thread() {
@Override
public void run() {
super.run();
try {
//1、实例化一个url对象【参数:你要访问的接口地址】
URL url = new URL("http://www.imooc.com/api/teacher?type=3&cid=1");
//2、获取HttpUrlConnection对象
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
//3、设置请求连接属性
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setReadTimeout(6000);
//4、获取响应吗,判断是否连接成功,若连接成功,则读取输入流并解析
if (httpURLConnection.getResponseCode() == 200) {
//4-1、获取输入流
InputStream is = httpURLConnection.getInputStream();
byte[] b = new byte[1024 * 512];
int length = 0;
//4-2、建立缓存流,保存所读取的字节数组
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((length = is.read(b)) > -1) {
//4-3、将读取的字节数组写入到缓存流中
baos.write(b, 0, length);
}
Log.e("TAG", baos.toString());
//4-4、JSON数据解析
JSONObject object = new JSONObject(baos.toString());
int status = object.getInt("status");
String msg = object.getString("msg");
Log.e("TAG", status + " " + msg);
//若是对象就用JSONObject进行解析,若是数组则用JSONArray进行解析
JSONObject data = object.getJSONObject("data");
String title = data.getString("title");
String author = data.getString("author");
String content = data.getString("content");
Log.e("TAG", " 标题:" + title + " 作者:" + author + " 内容:" + content);
//将操作权交还主线程
Message message = handler.obtainMessage();
Essay essay = new Essay(title, author, content);
message.obj = essay;
//调用此方法则会触发主线程中handler对象中的重写的handleMessage方法
handler.sendMessage(message);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}.start();
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Essay essay = (Essay) msg.obj;
titleTextView.setText(essay.getTitle());
authorTextView.setText(essay.getAuthor());
contentTextView.setText(essay.getContent());
}
};
}
二、Gson数据解析
使用Gson来解析数据就方便多了,修改上面DetailActivity.java
中的代码,主要修改json数据解析的代码,下面将整个initData()
方法中的代码贴出来:
private void initData() {
new Thread() {
@Override
public void run() {
super.run();
try {
//1、实例化一个url对象【参数:你要访问的接口地址】
URL url = new URL("http://www.imooc.com/api/teacher?type=3&cid=1");
//2、获取HttpUrlConnection对象
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
//3、设置请求连接属性
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setReadTimeout(6000);
//4、获取响应吗,判断是否连接成功,若连接成功,则读取输入流并解析
if (httpURLConnection.getResponseCode() == 200) {
//4-1、获取输入流
InputStream is = httpURLConnection.getInputStream();
byte[] b = new byte[1024 * 512];
int length = 0;
//4-2、建立缓存流,保存所读取的字节数组
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((length = is.read(b)) > -1) {
//4-3、将读取的字节数组写入到缓存流中
baos.write(b, 0, length);
}
Log.e("TAG", baos.toString());
//4-4、JSON数据解析
JSONObject object = new JSONObject(baos.toString());
int status = object.getInt("status");
String msg = object.getString("msg");
Log.e("TAG", status + " " + msg);
//创建Gson对象
Gson gson = new Gson();
String data = object.getString("data");
Essay e = gson.fromJson(data, Essay.class);
//将操作权交还主线程
Message message = handler.obtainMessage();
//Essay essay = new Essay(title, author, content);
message.obj = e;
//调用此方法则会触发主线程中handler对象中的重写的handleMessage方法
handler.sendMessage(message);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}.start();
}
三、复杂数据的解析
数据接口如下:
{
"status": 1,
"data": [
{
"id": 1,
"name": "Tony老师聊shell——环境变量配置文件",
"picSmall": "http://img.mukewang.com/55237dcc0001128c06000338-300-170.jpg",
"picBig": "http://img.mukewang.com/55237dcc0001128c06000338.jpg",
"description": "为你带来shell中的环境变量配置文件",
"learner": 12312
}, {
"id": 2,
"name": "数学知识在CSS动画中的应用 ",
"picSmall": "http://img.mukewang.com/55249cf30001ae8a06000338-300-170.jpg",
"picBig": "http://img.mukewang.com/55249cf30001ae8a06000338.jpg",
"description": "数学知识与CSS结合实现酷炫效果",
"learner": 45625
}, {
"id": 3,
"name": "Oracle数据库开发必备利器之PL/SQL基础",
"picSmall": "http://img.mukewang.com/5523711700016d1606000338-300-170.jpg",
"picBig": "http://img.mukewang.com/5523711700016d1606000338.jpg",
"description": "Oracle数据库高级开发必备的基础。",
"learner": 41236
}, {
"id": 4,
"name": "Android见证消息推送时刻进阶篇",
"picSmall": "http://img.mukewang.com/551e470500018dd806000338-300-170.jpg",
"picBig": "http://img.mukewang.com/551e470500018dd806000338.jpg",
"description": "Android消息推送就在眼前,Come on",
"learner": 45456
}, {
"id": 5,
"name": "Avalon探索之旅基础教程——复杂绑定",
"picSmall": "http://img.mukewang.com/551de0570001134f06000338-300-170.jpg",
"picBig": "http://img.mukewang.com/551de0570001134f06000338.jpg",
"description": "前端迷您MVVM框架,Avalon复杂绑定属性篇。",
"learner": 56556
}, {
"id": 6,
"name": "Android-Service系列之断点续传下载",
"picSmall": "http://img.mukewang.com/552640c300018a9606000338-300-170.jpg",
"picBig": "http://img.mukewang.com/552640c300018a9606000338.jpg",
"description": "想升职加薪么?本章课程你值得拥有",
"learner": 48996
}, {
"id": 7,
"name": "JUnit—Java单元测试必备工具",
"picSmall": "http://img.mukewang.com/551b92340001c9f206000338-300-170.jpg",
"picBig": "http://img.mukewang.com/551b92340001c9f206000338.jpg",
"description": "Java单元测试利器!",
"learner": 13210
}, {
"id": 8,
"name": "细说Java多线程之内存可见性",
"picSmall": "http://img.mukewang.com/5518c3d7000175af06000338-300-170.jpg",
"picBig": "http://img.mukewang.com/5518c3d7000175af06000338.jpg",
"description": "用两种方式实现内存可见性",
"learner": 15051
}, {
"id": 9,
"name": "CSS动画实用技巧",
"picSmall": "http://img.mukewang.com/551b98ae0001e57906000338-300-170.jpg",
"picBig": "http://img.mukewang.com/551b98ae0001e57906000338.jpg",
"description": "教你使用CSS实现惊艳的动画效果!",
"learner": 15210
}, {
"id": 10,
"name": "C++远征之起航篇",
"picSmall": "http://img.mukewang.com/550b86560001009406000338-300-170.jpg",
"picBig": "http://img.mukewang.com/550b86560001009406000338.jpg",
"description": "C++亮点尽在其中",
"learner": 84545
}
],
"msg": "成功"
}
这时我们使用Android原生数据解析就比较麻烦了,而是用Gson进行数据解析就会简单许多。根据上面的接口,新建一个类Outline.java
,代码如下:
package com.demo.httpdemo;
public class Outline {
private int id;
private String name;
private String picSmall;
private String picBig;
private String description;
private String learner;
public Outline(int id, String name, String picSmall, String picBig, String description, String learner) {
this.id = id;
this.name = name;
this.picSmall = picSmall;
this.picBig = picBig;
this.description = description;
this.learner = learner;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPicSmall() {
return picSmall;
}
public void setPicSmall(String picSmall) {
this.picSmall = picSmall;
}
public String getPicBig() {
return picBig;
}
public void setPicBig(String picBig) {
this.picBig = picBig;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLearner() {
return learner;
}
public void setLearner(String learner) {
this.learner = learner;
}
}
以下实现的效果仅仅是将数据解析并打印出来(Logcat窗口),并不会在Activity中显示出来。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
private void initData() {
new Thread() {
@Override
public void run() {
try {
URL url = new URL("http://www.imooc.com/api/teacher?type=2");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setReadTimeout(6000);
if (httpURLConnection.getResponseCode() == 200) {
InputStream is = httpURLConnection.getInputStream();
byte[] b = new byte[1024 * 512];
int length = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((length = is.read(b)) > -1) {
baos.write(b, 0, length);
}
Log.e("TAG", baos.toString());
JSONObject object = new JSONObject(baos.toString());
/**
* Gson
* 1、解析普通的json对象
* 2、解析json数组
*/
Gson gson = new Gson();
String data = object.getString("data");
ArrayList<Outline> outlines = gson.fromJson(data, new TypeToken<ArrayList<Outline>>() {
}.getType());
for (int i = 0; i < outlines.size(); i++) {
Outline o = outlines.get(i);
Log.e("TAG", "id:" + o.getId() + " name:" + o.getName() + " picSmall:" + o.getPicSmall() +
" picBig:" + o.getPicBig() + " description:" + o.getDescription() + " learner" + o.getLearner());
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}.start();
}
private void initView() {
findViewById(R.id.btn_net).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, DetailActivity.class));
}
});
}
}
运行应用即可在Logcat窗口查看打印结果: