课程介绍:
- 什么是客户端(Client)?
享受服务的每一个用户
- 什么是服务端(Server)?
为客户端提供资源数据
1.什么是Http
HTTP 协议即超文本传送协议(Hypertext Transfer Protocol )
是 Web 联网的基 础,也是手机联网常用的协议之一,HTTP 协议是建立在 TCP 协议之上的一种应用。
HTTP 连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。
从建立连接到关闭连接的过程称为“一次连接”。
HTTP 提供了封装或者显示数据的具体形式。Socket 提供了网络通信的能力
1.一个URL是有哪些部分组成
概要:
GET:获取数据
相当于刷新朋友圈,返回新的朋友圈消息给你看(也可以理解去超市(相当于服务器)买东西(我要什么..),返回了笔和书本)
POST:提交数据
相当于发布一条朋友圈,发布后展示在朋友圈中(相当于把自己的东西打包后,发送给服务器,服务器更新数据展示出来)
区别:一个直接写在url上面,一个用一个盒子做起来
传输角度上:GET是明文的,POST是隐藏的,所以POST更安全
本质上:GET安全的、获取数据服务器的数据不会修改,POST提交数据,相当于写入操作服务器会被修改
幂等性:指同样的一次操作,进行一次和多次的操作对系统的资源产生的影响是一样的,GET是幂等性的,POST提交数据,会对服务器修改。
可缓存:GET获取数据是可以缓存的
1.如果直接在主线程里面访问网络操作(因为网络是一个很耗时的操作),它会被卡死报错
android.os.NetworkOnMainThreadException
举个例子:假如在家里面做饭,煤气灶上只有一个锅煮饭,而煮饭时间很长,
锅被卡死了,你不能锅煮其他的东西;那么就要开另外一个锅(线程)
解决方式:另开一个线程把网络访问放在这个线程里执行
new Thread(new Runnable(){
网络请求操作
}).start();
2.网络操作在新开的线程下执行,依旧会报错
Caused by: android.system.ErrnoException: android_getaddrinfo failed: EACCES (Permission denied)
解决方式:因为没有在AndroidManifest.xml中声明网络权限
3.完成以上两点再运行任然会报错
Only the original thread that created a view hierarchy can touch its views.
因为更新UI不能再子线程里进行,只能在主线程更新UI,而网络操作又得在子线程里面进行,在主线程操作网络就会闪退
要实现子线程更新主线程的有什么办法呢?Hanlder
或者使用 runOnUiThread();或者mTextView.post(); 这两个方法都能够是更新UI操作转到主线程进行
方法1:
runOnUiThread(new Runnable(){
@Override
public void run(){
mTextView.setText(result);//更新UI的操作
}
});
方法2:
mTextView.post(new Runnable(){
@Override
public void run(){
mTextView.setText(result);//更新UI的操作
}
});
GET完整代码
try {
//首先拿到URL对象
URL url = new URL("http://www.imooc.com/api/teacher?type=2&page=1");
//打开url对象的链接,获得connection链接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//设置超时时间30s
connection.setConnectTimeout(30 * 1000);
//设置请求方法类型 GET请求获取数据
connection.setRequestMethod("POST");
//设置请求的属性
//我希望拿到内容的格式是json
connection.setRequestProperty("Content-Type", "application/json");
//我希望拿到的字符集是UTF-8
connection.setRequestProperty("Charset", "UTF-8");
//我们希望接受到的字符集是UTF-8
connection.setRequestProperty("Accept-Charset", "UTF-8");
//发起连接
connection.connect();
//连接开始后
//获取信息
//获取请求码
int responseCode = connection.getResponseCode();
//拿到消息
String repsonseMessage = connection.getResponseMessage();
//如果请求成功
if (responseCode == HttpURLConnection.HTTP_OK) {//如果拿到请求码为200(HTTP_OK)
//拿到输入流
InputStream inputStream=connection.getInputStream();
//将将流转换成字符串
result = streamToString(inputStream);
//更新UI只能在主线程操作
//通过使用runOnUiThread()方法将更新UI操作放到主线程进行
runOnUiThread(new Runnable() {
@Override
public void run() {
//将数据转化成UTF-8的格式
result=decode(result);
//将拿到的数据展示出来(更新UI)
mTextView.setText(result);
}
});
}else{//如果请求失败
//TODO:error fail
Log.e(TAG,"run:error code"+responseCode+",message:"+repsonseMessage);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
与GET不一样,它不是直接把参数放在URL上,而是把数据打包好
//首先拿到URL对象type=2&page=1
URL url = new URL("http://www.imooc.com/api/teacher");
使用POST还要多加一些设置
//*使用POST还有设置运行的输入输出
connection.setDoOutput(true);
connection.setDoInput(true);
//POST不能使用缓存
connection.setUseCaches(false);
POST请求的数据打包
//*POST请求数据打包
String data = "username=" + getEncodeValue("abc") + "&number=" + getEncodeValue("123456");
//输出流写入数据
OutputStream outputStream = connection.getOutputStream();
//将我的打包好的数据写入
outputStream.write(data.getBytes());
outputStream.flush();//如果没满,要调用flush()方法:刷新释放缓冲区的资源
outputStream.close();//用完关闭,防止内存泄漏
POST完整代码:
try {
//首先拿到URL对象type=2&page=1
URL url = new URL("http://www.imooc.com/api/teacher");
//打开url对象的链接,获得connection链接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//设置超时时间30s
connection.setConnectTimeout(30 * 1000);
//设置请求方法类型 GET请求获取数据
connection.setRequestMethod("POST");
//设置请求的属性
//我希望拿到内容的格式是json
connection.setRequestProperty("Content-Type", "application/json");
//我希望拿到的字符集是UTF-8
connection.setRequestProperty("Charset", "UTF-8");
//我们希望接受到的字符集是UTF-8
connection.setRequestProperty("Accept-Charset", "UTF-8");
//*使用POST还有设置运行的输入输出
connection.setDoOutput(true);
connection.setDoInput(true);
//POST不能使用缓存
connection.setUseCaches(false);
//发起连接
connection.connect();
//*POST请求数据打包
String data = "username=" + getEncodeValue("abc") + "&number=" + getEncodeValue("123456");
//输出流写入数据
OutputStream outputStream = connection.getOutputStream();
//将我的打包好的数据写入
outputStream.write(data.getBytes());
outputStream.flush();//如果没满,要调用flush()方法:刷新释放缓冲区的资源
outputStream.close();//用完关闭,防止内存泄漏
//连接开始后
//获取信息
//获取请求码
int responseCode = connection.getResponseCode();
//拿到消息
String repsonseMessage = connection.getResponseMessage();
//如果请求成功
if (responseCode == HttpURLConnection.HTTP_OK) {//如果拿到请求码为200(HTTP_OK)
//拿到输入流
InputStream inputStream=connection.getInputStream();
//将将流转换成字符串
result = streamToString(inputStream);
//更新UI只能在主线程操作
//通过使用runOnUiThread()方法将更新UI操作放到主线程进行
runOnUiThread(new Runnable() {
@Override
public void run() {
//将数据转化成UTF-8的格式
result=decode(result);
//将拿到的数据展示出来(更新UI)
mTextView.setText(result);
}
});
}else{//如果请求失败
//TODO:error fail
Log.e(TAG,"run:error code"+responseCode+",message:"+repsonseMessage);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Json 全称 JavaScript Object Natation ,用来描述数据结构,它是基于纯文本的数据格式,是一种轻量级的数据交换格式。广泛应用于 服务端 与 客户端 的数据交互。
格式
Json 以 key-value的形式存储数据;
Key的取值 为 String
类型;
Value的取值 为 String
,boolean
,Number
,数组
,Object
,null
;
Json 串 以 {
开始, 以 }
结尾;
Json 串中 数组
是 以 [
开始, 以 ]
结尾;
Json 串中 Object
是 以 {
开始, 以 }
结尾;
下面是GET请求获取到URL:http://www.imooc.com/api/teacher?type=2&page=1 中的json数据
其中status:1 表示是int型的;“ ”表示是字符串型的;true or false表示是boolean类型的
data:[ ]是一个数组
data数组里面又有很多对象,对象里面又有属性
/**
* 完全映射json
*/
public class LessonResult {
//status:1表示整形,如果是"",表示String,如果是true or false表示boolean
private int mStatus;
//data:[]是一个数组,数组里面又包含很多对象,lesson是对应很多对象
private List mLessons;
public int getStatus() {
return mStatus;
}
public void setStatus(int status) {
mStatus = status;
}
public List getLessons() {
return mLessons;
}
public void setLessons(List lessons) {
mLessons = lessons;
}
@Override
public String toString() {
return "LessonResult{" +
"mStatus=" + mStatus +
", mLessons=" + mLessons +
'}';
}
//data数组里面的对象类
public static class Lesson {
private int mID;//获取数组data里面的id
private int mLearnerNumber;//获取数组data里面的LearnerNumber
private String mName;//
private String mSmallPictureUrl;
private String mBigPictureUrl;
private String mDescription;
public int getmID() {
return mID;
}
public void setmID(int mID) {
this.mID = mID;
}
public int getmLearnerNumber() {
return mLearnerNumber;
}
public void setmLearnerNumber(int mLearnerNumber) {
this.mLearnerNumber = mLearnerNumber;
}
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
public String getmSmallPictureUrl() {
return mSmallPictureUrl;
}
public void setmSmallPictureUrl(String mSmallPictureUrl) {
this.mSmallPictureUrl = mSmallPictureUrl;
}
public String getmBigPictureUrl() {
return mBigPictureUrl;
}
public void setmBigPictureUrl(String mBigPictureUrl) {
this.mBigPictureUrl = mBigPictureUrl;
}
public String getmDescription() {
return mDescription;
}
public void setmDescription(String mDescription) {
this.mDescription = mDescription;
}
@Override
public String toString() {
return "Lesson{" +
"mID=" + mID +
", mLearnerNumber=" + mLearnerNumber +
", mName='" + mName + '\'' +
", mSmallPictureUrl='" + mSmallPictureUrl + '\'' +
", mBigPictureUrl='" + mBigPictureUrl + '\'' +
", mDescription='" + mDescription + '\'' +
'}';
}
}
}
通过代码一步一步获取json的数据,再返回到上面的类,通过toString方式显示出来
快速生成getter和setter方法,生成toString方法 MAC快捷键command+N;
try {
//新建一个jsonObject对象,获取我们GET请求得到的result(json格式)
JSONObject jsonObject = new JSONObject(result);
//读取json对象里面的status
int status = jsonObject.getInt("status");
LessonResult lessonResult = new LessonResult();
lessonResult.setStatus(status);//将读到的status给对象赋值
//读取json里面的数组,名称是data
JSONArray lessons = jsonObject.getJSONArray("data");
//创建一个List每一次都把Item里面的数据添加进去
List lessonList = new ArrayList<>();
//因为data数组里面还有很多对象,所以要循环取出
if (lessons != null && lessons.length() > 0) {
for (int index = 0; index < lessons.length(); index++) {
//拿到data里面的每一个item
JSONObject lesson = (JSONObject) lessons.get(index);
//拿到每一个item里面的对象的变量
int id = lesson.getInt("id");
int learner = lesson.getInt("learner");
String name = lesson.getString("name");
String smallPic = lesson.getString("picSmall");
String bigPic = lesson.getString("picBig");
String description = lesson.getString("description");
//把所有数据拿到后给对象赋值
LessonResult.Lesson lessonItem = new LessonResult.Lesson();
lessonItem.setmID(id);
lessonItem.setmName(name);
lessonItem.setmSmallPictureUrl(smallPic);
lessonItem.setmBigPictureUrl(bigPic);
lessonItem.setmDescription(description);
lessonItem.setmLearnerNumber(learner);
lessonList.add(lessonItem);//每一次都把数据添加到List里面
}
//循环结束把lessonList设置到Lessons里面
lessonResult.setLessons(lessonList);
}
mTextView.setText(lessonResult.toString());
} catch (JSONException e) {
e.printStackTrace();
}
使用Gson解析数据,谷歌的json解析;