目录
- 写在前面的话
- 一、HTTP协议
- 二、访问网络
-
- (一)概述
- (二)测试-浏览网络图片
- 三、开源项目-网络请求
-
- (一)概述
- (二)测试-AsyncHttpClient+SmartImageView
- 四、补充
写在前面的话
1、参考自:https://b23.tv/NwYxbp
2、内容如果有不对的,希望可以指出或补充。
3、新知识。
一、HTTP协议
超文本传输协议(Hyper Text Transfer Protocol,HTTP):规定了浏览器和服务器间相互通信的规则。是一种请求/响应式(客户端发送请求,服务端产生响应)的协议。整个响应的过程就是HTTP通信过程。
- HTTP请求:当客户端与服务器建立连接后,向服务器端发送的请求
- HTTP响应:当服务器端接收到客户端的请求后会做出响应,如返回数据。
二、访问网络
(一)概述
1、GET和POSTGET请求方式:以实体的方式得到由请求URL所指向的资源信息,它向服务器提交的参数跟在(拼接)请求URL后面 [ 浏览器地址栏中可以看到 ] ,参数和URL间用“?”隔开,每一个参数间用“&”隔开。
使用该方式访问网络,URL的长度(参数也是)一般需小于1k(1K=1KB=1024Bytes)
。
注意:使用URLEncoder.encode(“值”)对参数进行URL编码(因为需要传到浏览器地址栏中)。
POST请求方式:向服务器发出请求时需要在请求后附加实体。它向服务器提交的参数在请求后的实体中(请求体中),
该方式对URL的长度没有限制
。采用该方式提交数据时,用户在浏览器中看不到向服务器提交的请求参数,
因此POST方式相较GET方式更安全
。
无论时GET还是POST都需要注意编码方式的一致(客户端与服务端)。
2、HttpURLConnection访问网络使用步骤需要new子线程
。
从安卓6.0开始,Google已经移除了HttpClient库的支持,
推荐使用HttpURLConnection
。
创建url→创建HttpURLConnection对象→设置请求方式、超时时间(防止连接被阻塞时无响应),获取服务器返回的输入流→关闭HTTP连接
3、Handler消息机制在Android联网操作中,都是在子线程中
。
是一种异步回调机制,主要负责主线程(主要就是UI界面)与子线程(耗时的操作)进行通信。其主要对象(四个关键对象):
- Message:消息。
- Handler:处理者,主要负责Message的发送与处理。
- MessageQueue:消息队列,主要用来存放Handler发送过来的消息,并按照
的规则执行。先入先出
- Looper:消息循环,不断地从MessageQueue中抽取Message并交给Handler处理。
大概使用流程:Handler发送Message→存入MessageQueue→通过Looper取出Message→Handler处理Message→在HandlerMessage()中进行处理
(二)测试-浏览网络图片
功能:查看网络上的图片(使用HttpURLConnection的GET请求获取网络图片)。
1 依赖-项目清单文件

2 布局
2 主要代码
MainActivity.java
package com.example.testhttp;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private static final int CHANGE_UI = 1;//创建常量
private static final int ERROR = 2;
private HttpURLConnection conn;
private EditText testEd;
private ImageView testImg;
//在主线程创建消息处理器Handler
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what == CHANGE_UI){
Bitmap bitmap = (Bitmap) msg.obj;
testImg.setImageBitmap(bitmap);//
}else if(msg.what == ERROR){
Toast.makeText(MainActivity.this,"显示错误",Toast.LENGTH_SHORT).show();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取控件
testEd = findViewById(R.id.test_ed);
testImg = findViewById(R.id.test_img);
}
public void test(View view){
//获取到输入地址
String path = testEd.getText().toString().trim();
//判断输入是否为空
if(TextUtils.isEmpty(path)){
Toast.makeText(this,"不能为空",Toast.LENGTH_SHORT).show();
}else {
//在子线程中请求网络
new Thread(){ //开启一个线程
private Bitmap bitmap;
@Override
public void run() {
//连接服务器GET请求获取到图片
try {
URL url = new URL(path);//创建url
//根据url发送HTTP请求
conn = (HttpURLConnection) url.openConnection();
//设置
conn.setRequestMethod("GET");//请求方式
conn.setConnectTimeout(5000);//超时时间5秒
int code = conn.getResponseCode();//得到服务端返回的响应码
//请求网络成功的返回码为200
if(code == 200){
//获取输入流,里面就是想要的信息
InputStream is = conn.getInputStream();
//is转换为Bitmap对象
bitmap = BitmapFactory.decodeStream(is);
///将更改主界面的消息发送给主线程
Message msg = new Message();
msg.what = CHANGE_UI;//用于区分不同的消息
msg.obj = bitmap;//携带对应的数据
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
Message msg = new Message();
msg.what = ERROR;
handler.sendMessage(msg);
}
///关闭连接
conn.disconnect();
}
}.start();
}
}
}
3 效果展示
运行结果如下。
三、开源项目-网络请求
Day22内容。
(一)概述
1、AsyncHttpClientAsyncHttpClient:Async就是异步的意思。可以处理异步(多条线程中处理任务)HTTP请求,也就是
会自动开启一个子线程
,并通过匿名内部类处理回调结果。将对应的方法做了封装。需要导入。
HTTP异步请求都是位于非UI线程中,不会阻塞UI操作,AsyncHttpClient通过线程池处理并发请求,处理文件上传、下载,
响应结果自动成JSON格式
。
AsyncHttpClient常用类:
- AsyncHttpClient:异步客户端请求的类,提供了get、put、post、delete、head等请求方法。
- AsyncHttpResponseHandler:继承自ResponseHandlerInterface。是访问网络后回调的接口,接收请求结果,如果访问成功则回调其中的OnSucess方法,否则回调OnFailure方法。
SmartImageView:主要用于加速从网络上加载图片,它继承自Android自带的ImageView组件。需要导入也需要布局。
(二)测试-AsyncHttpClient+SmartImageView
功能:解析服务器上的JSON文件并将其显示到ListView控件上。
1、依赖SmartImageView的jar包下载
对应的build.gradle文件
清单文件
① 配置服务器
下载apache-tomcat-8.5.61.zip
② 启动服务器
③ 测试
test_activity.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">
<!--嵌套部分-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--进度条部分-->
<LinearLayout
android:id="@+id/show_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="visible">
<!--进度条-->
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在加载中..."/>
</LinearLayout>
<!--展示部分ListView-->
<ListView
android:id="@+id/show_news"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"/>
</FrameLayout>
</LinearLayout>
test_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="70dp">
<!--加载图片部分-->
<com.loopj.android.image.SmartImageView
android:id="@+id/item_img"
android:layout_width="80dp"
android:layout_height="60dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="5dp"
android:layout_centerInParent="true"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher"/>
<!--文本部分-->
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@id/item_img"
android:text="标题"
android:textColor="@color/black"
android:textSize="18sp" />
<TextView
android:id="@+id/item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/item_title"
android:layout_toRightOf="@id/item_img"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:text="描述"
android:textSize="14sp" />
<TextView
android:id="@+id/item_talk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dp"
android:layout_marginRight="10dp"
android:text="评论"
android:textSize="12sp"
android:layout_marginLeft="60dp"
android:layout_gravity="bottom"
android:textColor="#aaaaaa"/>
</RelativeLayout>
4、代码 NewsInfo.java
package com.example.testhttp;
//JSON数据内容
public class NewsInfo {
//字段名与JSON文件数据字段一致
private String icon;//图片路径
private String title;//标题
private String content;//描述的内容
private int type;//类型
private long comment;//评论数
public NewsInfo(String icon, String title, String content, int type, long comment) {
this.icon = icon;
this.title = title;
this.content = content;
this.type = type;
this.comment = comment;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public long getComment() {
return comment;
}
public void setComment(long comment) {
this.comment = comment;
}
}
JsonParse.java
为了方便以后更改,做如下的添加。
Test2.java
package com.example.testhttp;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.image.SmartImageView;
import java.util.List;
import cz.msebera.android.httpclient.Header;
public class Test2 extends AppCompatActivity {
//test_activity
private LinearLayout showLoading;
private ListView showNews;
//test_item
private SmartImageView itemImg;
private TextView itemTitle,itemText,itemTalk;
private List<NewsInfo> newsInfoList;//声明集合
private NewsInfo newsInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_activity);
//获取到控件
showLoading = findViewById(R.id.show_loading);
showNews = findViewById(R.id.show_news);
//填充数据
fillData();//调用
}
//使用AsyncHttpClient访问网络
private void fillData() {
//创建AsyncHttpClient对象
AsyncHttpClient client = new AsyncHttpClient();
//默认为GET请求方式
client.get(getString(R.string.server_url), new AsyncHttpResponseHandler() {
@Override
//请求成功
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
//调用JsonParse工具类解析JSON文件数据
String json = new String(responseBody, "utf-8");//转换为json数据
newsInfoList = JsonParse.getNewsInfo(json);
if (newsInfoList == null) {
Toast.makeText(Test2.this, "解析失败", Toast.LENGTH_SHORT).show();
} else {
//更新界面
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
showLoading.setVisibility(View.INVISIBLE);//进度条改成不显示
showNews.setAdapter(new NewsAdapter());//展示
}
},5000);//5秒后执行
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Toast.makeText(Test2.this, "请求失败", Toast.LENGTH_SHORT).show();
}
});
}
//ListView适配器
private class NewsAdapter extends BaseAdapter {
//条目对象
@Override
public Object getItem(int position) {
return null;
}
//条目id
@Override
public long getItemId(int position) {
return 0;
}
@Override
//listview的条目数
public int getCount() {
return newsInfoList.size();
}
@Override
//获取到条目信息view
public View getView(int position, View convertView, ViewGroup parent) {
View view = View.inflate(Test2.this, R.layout.test_item, null);
//获取控件
itemImg = view.findViewById(R.id.item_img);
itemTitle = view.findViewById(R.id.item_title);
itemText = view.findViewById(R.id.item_text);
itemTalk = view.findViewById(R.id.item_talk);
newsInfo = newsInfoList.get(position);//获取到要显示的数据
//SmartImageView加载指定路径的图片
//参数1:具体路径,参数2、3:显示成功/失败加载的图片
itemImg.setImageUrl(newsInfo.getIcon(), R.mipmap.ic_launcher, R.mipmap.ic_launcher);
//设置标题
itemTitle.setText(newsInfo.getTitle());
//设置描述文字
itemText.setText(newsInfo.getContent());
//设置类型
int type = newsInfo.getType();
switch (type) {
//不同新闻类型设置不同的颜色和不同的内容
//其他的则是默认的文字内容
case 1:
itemTalk.setText("评论数:" + newsInfo.getComment());
break;
case 2:
//红色的专题文字
itemTalk.setTextColor(Color.RED);
itemTalk.setText("专题新闻");
break;
case 3:
itemTalk.setTextColor(Color.BLUE);
itemTalk.setText("LIVE");
break;
}
return view;//返回条目信息
}
}
}
5、效果展示 运行结果如下。
四、补充
1、com.google.gson.stream.MalformedJsonException报错的解决办法
我发生的问题是源自JSON数据的问题,格式多了个在“}”前多了个“,”。