实验目的
- 学会使用HttpURLConnection请求访问Web服务
- 学习Android线程机制,学会线程更新UI
- 学会解析JSON数据
- 学习CardView布局技术
效果
添加依赖
//json解析类
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
//rxjava类
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.4'
//recyclerview ui
implementation 'com.android.support:recyclerview-v7:28.0.0'
//cardview ui
implementation'com.android.support:cardview-v7:28.+'
本例使用的
RxJava
是2.2.4版本,与1.X版本有较大区别!!!
添加权限
在app/src/main/AndroidManifest.xml
中添加
<uses-permission android:name="android.permission.INTERNET"/>
这次的网络访问权限不用动态申请啦!!!
但是
高版本(Android 8
以上)的SDK
可能会报这样的错误
Cleartext HTTP traffic to xxx not permitted
Google表示,为保证用户数据和设备的安全,针对下一代 Android 系统(Android P) 的应用程序,将要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的连接,因此运行 Android P 系统的安卓设备无论是接收或者发送流量,未来都不能明码传输
这里采用最简单的办法
在app/src/main/AndroidManifest.xml
中的application
中添加
android:usesCleartextTraffic="true"
强行使用明文传输
更多办法:https://stackoverflow.com/questions/45940861/android-8-cleartext-http-traffic-not-permitted
使用HttpURLConnection
获取网络数据
示例API
网址: https://space.bilibili.com/ajax/top/showTop?mid=2
URL url = new URL(baseURL + "showTop?mid=" + editText.getText().toString());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode() == 200){
//InputStream转String
BufferedInputStream bis = new BufferedInputStream((InputStream)conn.getContent());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int result = bis.read();
while(result != -1) {
byteArrayOutputStream.write((byte) result);
result = bis.read();
}
//结果是byteArrayOutputStream.toString()
}
这样子就可以通过byteArrayOutputStream.toString()
得到字符串
不过字符串是JSON
类型数据,需要解析才能方便使用
JSON
解析类
观察网页返回的json
结果
{
"status":true,"data":{
"aid":349,"state":0,"cover":"http:\/\/i2.hdslb.com\/bfs\/archive\/8d15f47650e6e95e11ad7a3d6ae06ea52231169a.jpg","title":"[\u4eba\u751f\u7684\u5bfc\u5e08\u677e\u5188\u4fee\u9020]\u6771\u65b9\u4fee\u5922\u9020","content":"sm5159640","play":186049,"duration":"01:23","video_review":936,"create":"2009-09-08 17:00:16","rec":"e'm'm'm'm'm","count":1}}
根据json
中的属性新建实体类RecyclerObj.java
实体类中不要求实现所有的属性
import android.graphics.Bitmap;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
public class RecyclerObj {
@SerializedName("status")
private Boolean status;
@SerializedName("data")
private data idata;
public static class data {
@SerializedName("aid")
private String aid;
@SerializedName("title")
private String title;
@SerializedName("cover")
private String cover;
@SerializedName("play")
private String play;
@SerializedName("duration")
private String duration;
//评论
@SerializedName("video_review")
private String video_review;
@SerializedName("create")
private String create;
@SerializedName("content")
private String content;
public String getAid() {
return aid;
}
public String getTitle() {
return title;
}
public String getPlay() {
return play;
}
public String getVideo_review() {
return video_review;
}
public String getContent() {
return content;
}
public String getCover() {
return cover;
}
public String getCreate() {
return create;
}
public String getDuration() {
return duration;
}
}
public Boolean getStatus() {
return status;
}
public data getIdata() {
return idata;
}
}
后来就可以使用new Gson().fromJson(byteArrayOutputStream.toString(), RecyclerObj.class)
将
String
转换为RecyclerObj
对象了
还有个实体类PreviewObj.java
用来获取预览图的链接返回的JSON
数据
package com.sysu.janking.httpapi;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
public class PreviewObj {
@SerializedName("code")
private int code;
@SerializedName("data")
private data idata;
public static class data {
@SerializedName("img_x_len")
private int img_x_len;
@SerializedName("img_y_len")
private int img_y_len;
@SerializedName("img_x_size")
private int img_x_size;
@SerializedName("img_y_size")
private int img_y_size;
@SerializedName("image")
private ArrayList<String> image;
@SerializedName("index")
private ArrayList<Integer> index;
public ArrayList<String> getImage() {
return image;
}
public int getImg_x_len() {
return img_x_len;
}
public int getImg_x_size() {
return img_x_size;
}
public int getImg_y_len() {
return img_y_len;
}
public int getImg_y_size() {
return img_y_size;
}
public ArrayList<Integer> getIndex() {
return index;
}
}
public data getIdata() {
return idata;
}
public int getCode() {
return code;
}
}
结合RxJava
但是像上面一样直接运行的话会报NetworkOnMainThreadException
的异常,因为网络访问不能在主线程中进行,容易造成阻塞或者UI瘫痪
在MainActivity.java
中添加被观察者
private CompositeDisposable mCompositeDisposable = new CompositeDisposable();
private Observable<RecyclerObj> observable = Observable.create(new ObservableOnSubscribe<RecyclerObj>() {
@Override
public void subscribe(ObservableEmitter<RecyclerObj> observableEmitter) throws Exception {
URL url = new URL(baseURL + "showTop?mid=" + editText.getText().toString());
HttpURLConnection conn = (HttpURLConnection)url.