目标
- 了解HTTP协议通信简介,能够说出什么是HTTP协议
- 掌握HttpURLConnection的使用方法,能够使用HttpURLConnection访问网络
- 掌握WebView控件的使用方式,能够使用WebView控件加载不同的网页
- 掌握JSON数据的解析,能够通过不同的方式解析JSON数据
- 熟悉Handler消息机制的概述,能够归纳Handler消息机制的原理
在移动互联网时代,手机联网实现信息互通是最基本的功能体验。例如,在上下班的途中或旅行时,只要有时间人们就会拿出手机上网,通过手机接收新资讯、搜索网络资源。Android作为智能手机市场中主流的操作系统,它的强大离不开其对网络功能的支持。Android系统提供了多种实现网络通信的方式。接下来,我们从最基础的HTTP协议开始,到Android中原生的HttpURLConnection、WebView控件的使用以及网络数据的解析进行详细讲解。
一、通过HTTP访问网络
- 了解HTTP协议通信简介,能够说出什么是HTTP协议
- 掌握HttpURLConnection的使用方法,能够使用HttpURLConnection访问网络
1.1 HTTP协议通信简介
HTTP(Hyper Text Transfer Protocol)即超文本传输协议
,它规定了浏览器
和服务器
之间相互通信的规则。
HTTP协议是一种请求/响应式的协议。
-
当客户端与服务器端建立连接后,向服务器端发送的请求,称作HTTP请求。
-
当服务器端接收到请求后会做出响应,称为HTTP响应。
使用手机客户端访问百度时,会发送一个HTTP请求,当服务器端接收到请求后,会做出响应并将百度页面(数据)返回给客户端浏览器,这个请求响应的过程就是HTTP通信的过程。
1.2 使用HttpURLConnection访问网络
GET与POST请求
(1)GET方式
GET方式是以实体的方式得到由请求URL所指向的资源信息,它向服务器提交的参数跟在请求URL后面。使用GET方式访问网络URL的长度一般要小于1KB。
(2)POST方式
POST方式向服务器发出请求时需要在请求后附加实体。它向服务器提交的参数在请求后的实体中,POST方式对URL的长度是没有限制的。
采用POST方式提交数据时,用户在浏览器中看不到向服务器提交的请求参数,因此POST方式要比GET方式相对安全。
GET方式提交数据
//将用户名和密码拼在指定资源路径后面,并对用户名和密码进行编码
String path = "http://192.168.1.100:8080/web/LoginServlet?username="
+ URLEncoder.encode("zhangsan")
+"&password="+ URLEncoder.encode("123");
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int responseCode = conn.getResponseCode(); //获取到状态码
if(responseCode == 200){ //状态码为200,表示访问成功获取返回内容的输入流
InputStream is = conn.getInputStream();
}
POST方式提交数据
URL url = new URL("http://192.168.1.100:8080/web/LoginServlet");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("POST");
//准备数据并给参数进行编码
String data = "username=" + URLEncoder.encode("zhangsan")
+ "&password=" + URLEncoder.encode("123");
//设置请求头数据提交方式以及提交数据的长度,这里是以form表单的方式提交
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", data.length() + "");
//以流的形式将数据写到服务器上
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(data.getBytes());
int code = conn.getResponseCode();
if (code == 200) {
InputStream is = conn.getInputStream();
}
注意
在实际开发中,手机端与服务器端进行交互的过程中避免不了要提交中文到服务器,这时就会出现中文乱码的情况。无论是GET方式还是POST方式提交参数时都要给参数进行编码,编码方式必须与服务器解码方式一致。同样在获取服务器返回的中文字符时,也需要用指定格式进行解码。
二、使用WebView进行网络开发
目标
- 掌握WebView的使用方式,能够使用WebView浏览不同网页、执行HTML代码和支持JavaScript
2.1 使用WebView浏览网页
在Android程序中,WebView控件可以在XML布局文件中使用标签来添加,也可以在Java文件中通过new关键字来创建。
通常会采用在XML布局文件中添加标签的形式,具体代码如下
<!--WebView控件的id-->
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
控件的常用方法如下表所示。
属性名称 | 功能描述 |
---|---|
loadUrl(String url) | 用于加载指定URL对应的网页 |
loadData(String data, String mimeType, String encoding) | 用于将指定的字符串数据加载到浏览器中 |
loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding,String historyUrl) | 基于URL加载指定的数据 |
capturePicture() | 用于创建当前屏幕的快照 |
goBack() | 用于执行后退操作,相当于浏览器上后退按钮的功能 |
goForward() | 用于执行前进操作,相当于浏览器上前进按钮的功能 |
stopLoading() | 用于停止加载当前页面 |
reload() | 用于刷新当前页面 |
emulator.exe -list-avds
emulator.exe -avd Nexus_4_API_28 -dns-server 192.168.1.1
setprop net.dns1 192.168.1.1
setprop net.eth0.dns1 192.168.1.1
setprop net.eth0.gw 192.168.1.1
接下来通过一个案例来演示如何使用WebView控件加载网页,本案例的界面效果如下图所示。
放置界面控件 res\layout\activity_main.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="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
编写界面交互代码 webview\MainActivity.java
package cn.itcast.webview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取布局管理器中添加的WebView控件
WebView webview=findViewById(R.id.webView);
webview.loadUrl("http://m.itheima.com/"); // 指定要加载的网页
}
}
在MainActivity中实现WebView控件浏览网页的功能,通过WebView控件的loadUrl()方法来加载指定的网页,主要代码如下。
WebView webview=(WebView)findViewById(R.id.webView);
webview.loadUrl("http://www.itheima.com/"); //通过加载网页地址加载网页
需要在清单文件(AndroidManifest.xml)的< manifest>标签中<font color='cornflowerblue'>添加允许访问网络资源的权限</font>。
注 意
如果想让上述WebView控件具备放大和缩小网页的功能,则需要对该控件进行如下设置:
//设置WebView控件支持使用屏幕控件或手势进行缩放
webview.getSettings().setSupportZoom(true);
//设置WebView控件使用其内置的变焦机制,该机制集合屏幕缩放控件使用
webview.getSettings().setBuiltInZoomControls(true);
2.2 使用WebView执行HTML代码
WebView类提供了loadData()和 loadDataWithBaseURL()方法加载HTML代码。当使用loadData()方法来加载带中文的HTML内容时会产生乱码,但是使用loadDataWithBaseURL()方法就不会出现这种情况。loadDataWithBaseURL()方法的定义方式如下:
接下来通过一个案例来演示如何使用WebView控件加载HTML代码,本案例的界面效果如下图所示。
放置界面控件 res\layout\activity_main.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="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
实现加载HTML的功能 webviewhtml\MainActivity.java
package cn.itcast.webviewhtml;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取布局管理器中添加的WebView控件
WebView webview = findViewById(R.id.webView);
// 创建一个字符串构建器,将要显示的HTML内容放置在该构建器中
StringBuilder sb = new StringBuilder();
sb.append("<div>请选择您要学习的课程:</div>");
sb.append("<ul>");
sb.append("<li>新媒体课程</li>");
sb.append("<li>大数据课程</li>");
sb.append("<li>人工智能课程</li>");
sb.append("</ul>");
// 加载数据
// null 表示默认的空白页面
// sb.toString() sb中的数据
// "text/html" 指定要显示内容的MIME类型
webview.loadDataWithBaseURL(null, sb.toString(), "text/html", "utf-8",
null);
}
}
2.3 设置WebView支持JavaScript
为了解决WebView控件在默认情况下不支持JavaScript代码的问题,我们需要通过setJavaScriptEnabled()方法来设置WebView控件,使其可以支持JavaScript代码。
WebSettings settings= webview.getSettings(); // 获取WebSettings对象
settings.setJavaScriptEnabled(true); //设置JavaScript可用
//使WebView控件显示带有JavaScript代码的提示框
webview.setWebChromeClient(new WebChromeClient());
接下来通过一个案例来演示如何使用WebView控件支持一个带有JavaScript代码的网页,本案例的界面效果如下图所示。
导入JS文件 src\main\assets\alert.html和alert.js
<!DOCTYPE html>
<html>
<head>
<title>alert.html</title>
<meta charset="UTF-8">
<meta name="content-type" content="text/html; charset=UTF-8">
</head>
<body>
This is my HTML page.
<br>
<script type="text/javascript" src="alert.js"></script>
<script type="text/javascript">
alert("我是一个消息提示框");
</script>
</body>
</html>
window.alert = function(msg, callback) {
var div = document.createElement("div");
div.innerHTML = "<style type=\"text/css\">"
+ ".nbaMask { position: fixed; z-index: 1000; top: 0; right: 0; left: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); } "
+ ".nbaMaskTransparent { position: fixed; z-index: 1000; top: 0; right: 0; left: 0; bottom: 0; } "
+ ".nbaDialog { position: fixed; z-index: 5000; width: 80%; max-width: 300px; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); background-color: #fff; text-align: center; border-radius: 8px; overflow: hidden; opacity: 1; color: white; }"
+ ".nbaDialog .nbaDialogHd { padding: .2rem .27rem .08rem .27rem; } "
+ ".nbaDialog .nbaDialogHd .nbaDialogTitle { font-size: 17px; font-weight: 400; } "
+ ".nbaDialog .nbaDialogBd { padding: 0 .27rem; font-size: 15px; line-height: 1.3; word-wrap: break-word; word-break: break-all; color: #000000; } "
+ ".nbaDialog .nbaDialogFt { position: relative; line-height: 48px; font-size: 17px; display: -webkit-box; display: -webkit-flex; display: flex; } "
+ ".nbaDialog .nbaDialogFt:after { content: \" \"; position: absolute; left: 0; top: 0; right: 0; height: 1px; border-top: 1px solid #e6e6e6; color: #e6e6e6; -webkit-transform-origin: 0 0; transform-origin: 0 0; -webkit-transform: scaleY(0.5); transform: scaleY(0.5); } "
+ ".nbaDialog .nbaDialogBtn { display: block; -webkit-box-flex: 1; -webkit-flex: 1; flex: 1; color: #09BB07; text-decoration: none; -webkit-tap-highlight-color: transparent; position: relative; margin-bottom: 0; } "
+ ".nbaDialog .nbaDialogBtn:after { content: \" \"; position: absolute; left: 0; top: 0; width: 1px; bottom: 0; border-left: 1px solid #e6e6e6; color: #e6e6e6; -webkit-transform-origin: 0 0; transform-origin: 0 0; -webkit-transform: scaleX(0.5); transform: scaleX(0.5); } "
+ ".nbaDialog a { text-decoration: none; -webkit-tap-highlight-color: transparent; }"
+ "</style>"
+ "<div id=\"dialogs2\" style=\"display: none\">"
+ "<div class=\"nbaMask\"></div>"
+ "<div class=\"nbaDialog\">"
+ " <div class=\"nbaDialogHd\">"
+ " <strong class=\"nbaDialogTitle\"></strong>"
+ " </div>"
+ " <div class=\"nbaDialogBd\" id=\"dialog_msg2\">弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内</div>"
+ " <div class=\"nbaDialogHd\">"
+ " <strong class=\"nbaDialogTitle\"></strong>"
+ " </div>"
+ " <div class=\"nbaDialogFt\">"
+ " <a href=\"javascript:;\" class=\"nbaDialogBtn nbaDialogBtnPrimary\" id=\"dialog_ok2\">确定</a>"
+ " </div></div></div>";
document.body.appendChild(div);
var dialogs2 = document.getElementById("dialogs2");
dialogs2.style.display = 'block';
var dialog_msg2 = document.getElementById("dialog_msg2");
dialog_msg2.innerHTML = msg;
// var dialog_cancel = document.getElementById("dialog_cancel");
// dialog_cancel.onclick = function() {
// dialogs2.style.display = 'none';
// };
var dialog_ok2 = document.getElementById("dialog_ok2");
dialog_ok2.onclick = function() {
dialogs2.style.display = 'none';
callback();
};
};
放置界面控件 res\layout\activity_main.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">
<Button
android:id="@+id/btn_dialog"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="执行JAVASCRIPT代码并弹出提示框"
android:layout_margin="8dp"
android:textColor="@android:color/white"
android:background="@drawable/btn_dialog_selector"/>
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
创建背景选择器 res\drawable\btn_dialog_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_dialog_selected"
android:state_pressed="true" />
<item android:drawable="@drawable/btn_dialog_normal" />
</selector>
实现加载JS代码功能 webviewjs\MainActivity.java
package cn.itcast.webviewjs;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final WebView webview = findViewById(R.id.webView);
Button btn = findViewById(R.id.btn_dialog);
webview.loadUrl("file:///android_asset/alert.html"); //指定要加载的网页
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 设置webview控件支持JavaScript代码
webview.getSettings().setJavaScriptEnabled(true);
// 显示网页中通过JavaScript代码弹出的提示框
webview.setWebChromeClient(new WebChromeClient());
webview.loadUrl("file:///android_asset/alert.html");
};
});
}
}
三、JSON数据解析
目标
- 掌握JSON数据的解析,能够通过不同的方式解析JSON数据
3.1 JSON数据
JSON数据的特点
(1)JSON即JavaScript Object Notation(对象表示法),是一种轻量级的数据交换格式。
(2)JSON是基于纯文本的数据格式,它可以传输String、Number、Boolean类型的数据,也可以传输数组或者Object对象。
(3)JSON文件的扩展名为.json。
(4)JSON分为JSON对象和JSON数组两种数据结构。
对象结构的JSON数据
以“{”开始,以“}”结束。中间部分由0个或多个以“,”分隔的key:value对构成,注意关键字和值之间以“:”分隔。
关键字key必须为String类型,值value可以是String、Number、Object、Array等数据类型。
数组结构的JSON数据
以“[”开始,以“]”结束。中间部分由0个或多个以“,”分隔的值的列表组成。
值value可以是String、Number、Boolean、null等数据类型。
注意:
使用JSON存储单个数据(如“abc”),一定使用数组结构,因为对象结构必须是由“key:value”的形式构成。
3.2 JSON解析
两种解析方式
-
org.json
- Android SDK中为开发者提供的,通过使用JSONObject和JSONArray两个类完成对JSON数据的解析。
-
Gson
- 由Google公司提供的,在使用
Gson库
之前,首先需要将gson.jar添加到项目中,然后才能调用其提供的方法。
- 由Google公司提供的,在使用
解析JSON对象
例如,要解析的JSON数据如下:
{ "name": "zhangsan", "age": 27, "married":true } //json1 一个json对象
[{"name": "lisi","age": 25},{"name": "Jason","age": 20}] //json2 一个json数组
使用JSONObject解析JSON对象:
optXXX()方法在解析数据时比getXXX()方法更安全,如果对应字段不存在,optXXX()方法会返回空值或者0,而getXXX()方法会抛出异常。
JSONObject jsonObj = new JSONObject(json1);
String name = jsonObj.optString("name");
int age = jsonObj.optInt("age");
boolean married = jsonObj.optBoolean("married");
解析JSON数组
使用JSONArray解析JSON数组:
数组的解析方法和对象类似,只是将key值替换为数组中的下标。
JSONArray jsonArray = new JSONArray(json2);
for(int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObj = jsonArray.getJSONObject(i);
String name = jsonObj.optString("name");
int age = jsonObj.optInt("age");
}
Gson库解析JSON数据
例如,要解析的JSON数据如下(与org.json解析数据相同):
使用Gson库前,首先需要将gson.jar添加到项目中,并且创建JSON数据对应的实体类Person1与Person2,需要注意的是,实体类中的成员名称要与JSON数据中的key值一致。
{ "name": "zhangsan", "age": 27, "married":true } //json1 一个json对象
[{"name": "lisi","age": 25},{"name": "Jason","age": 20}] //json2 一个json数组
使用Gson解析JSON对象
Gson gson = new Gson();
Person person1 = gson.fromJson(json1, Person1.class); //将JSON数据转换成对象
使用Gson解析JSON数组
Gson gson = new Gson();
//TypeToken是Google提供的一个解析JSON数据的类
Type listType = new TypeToken<List<Person2>>(){}.getType();
List<Person2> person2 = gson.fromJson(json2, listType);
Android Studio添加库文件
在Android程序中添加库文件进行讲解,具体操作步骤如下:
- 在Android Studio中,选择【File】à【Project Structure…】选项,此时会弹出一个Project Structure窗口,如下图所示。
- 选中Project Structure窗口中的【Dependencies】选项卡,接着单击该窗口右上角的“ ”,选择Library dependency选项,此时会弹出一个Choose Library Dependency窗口,在该窗口中找到Gson库com.google.code.gson:gson:2.8.5并选中,如下图所示。
3.3 实战演练—仿拼多多砍价界面
本节我们将通过仿拼多多砍价界面的案例来演示如何解析JSON数据并将数据显示到界面上。本案例的界面效果如下图所示。
放置界面控件 res\layout\activity_main.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:background="@android:color/black"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:layout_marginRight="20dp"
android:background="@drawable/title_bg"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:text="一刀砍成卡"
android:textColor="#ce4032"
android:textSize="24sp"
android:textStyle="bold" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_margin="20dp"
android:background="#af560e" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="商品直接带回家"
android:textColor="#875a1e"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
搭建商品的条目布局 res\layout\goods_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="230dp"
android:layout_marginLeft="30dp"
android:layout_marginTop="20dp"
android:background="@android:color/black"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/goods_bg"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/tv_count"
android:layout_width="wrap_content"
android:layout_height="27dp"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:padding="5dp"
android:textColor="#573516"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_goods_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textColor="#573516"
android:textSize="16sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/iv_img"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="10dp" />
<Button
android:id="@+id/btn_free"
android:layout_width="110dp"
android:layout_height="35dp"
android:layout_margin="10dp"
android:background="@drawable/btn_free_bg"
android:text="点击免费拿"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
封装商品信息的实体类 pinduoduo\GoodsInfo.java
package cn.itcast.pinduoduo;
public class GoodsInfo {
private int id; // 商品id
private String count; // 已砍商品的数量
private String goodsName; // 商品名称
private String goodsPic; // 商品图片
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCount() {
return count;
}
public void setCount(String count) {
this.count = count;
}
public String getGoodsName() {
return goodsName;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}
public String getGoodsPic() {
return goodsPic;
}
public void setGoodsPic(String goodsPic) {
this.goodsPic = goodsPic;
}
}
编写商品列表的适配器 pinduoduo\GoodsAdapter.java
package cn.itcast.pinduoduo;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
public class GoodsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private List<GoodsInfo> GoodsList = new ArrayList<>();
public GoodsAdapter(Context context) {
this.mContext = context;
}
/**
* 获取数据更新界面
*/
public void setData(List<GoodsInfo> GoodsList) {
this.GoodsList = GoodsList; //获取从Activity界面传递过来的数据GoodsList
notifyDataSetChanged();
}
// inflate()方法加载布局文件
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = null;
RecyclerView.ViewHolder holder = null;
itemView = LayoutInflater.from(mContext).inflate(R.layout.goods_item, parent, false);
holder = new MyViewHolder(itemView);
return holder;
}
// 数据绑定
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
GoodsInfo bean = GoodsList.get(position);
// 将已砍的商品数量和商品名称设置到界面控件上
((MyViewHolder) holder).tv_count.setText("已砍" + bean.getCount() + "件");
((MyViewHolder) holder).tv_goods_name.setText(bean.getGoodsName());
// 将商品图片数据设置到图片控件iv_img上
Glide.with(mContext)
.load(bean.getGoodsPic())
.error(R.mipmap.ic_launcher)
.into(((MyViewHolder) holder).iv_img);
}
// 获取条目总数
@Override
public int getItemCount() {
return GoodsList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tv_count, tv_goods_name;
ImageView iv_img;
Button btn_free;
public MyViewHolder(View view) {
super(view);
tv_count = view.findViewById(R.id.tv_count);
tv_goods_name = view.findViewById(R.id.tv_goods_name);
iv_img = view.findViewById(R.id.iv_img);
btn_free = view.findViewById(R.id.btn_free);
}
}
}
实现商品显示功能 pinduoduo\MainActivity.java
package cn.itcast.pinduoduo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
private GoodsAdapter adapter; // 列表的适配器
public static final int MSG_GOODS_OK = 1; // 获取数据
private MHandler mHandler;
// 内网接口
public static final String WEB_SITE = "http://172.16.43.20:8080/goods";
// 商品列表接口
public static final String REQUEST_GOODS_URL = "/goods_list_data.json";
private RecyclerView rv_list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new MHandler();
init();
initData();
}
private void init() {
rv_list = findViewById(R.id.rv_list);
// this 表示上下文
// 2 表示商品列表的每个条目中显示两条商品信息
GridLayoutManager manager = new GridLayoutManager(this, 2);
// 将manager对象设置到控件rv_list上
rv_list.setLayoutManager(manager);
adapter = new GoodsAdapter(MainActivity.this);
// 将数据适配器的对象adapter设置到控件rv_list上
rv_list.setAdapter(adapter);
}
private void initData() {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(WEB_SITE +
REQUEST_GOODS_URL).build();
Call call = okHttpClient.newCall(request);
// 开启异步线程访问网络,从服务器上获取商品列表的数据
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
String res = response.body().string(); // 获取商品数据
Message msg = new Message();
msg.what = MSG_GOODS_OK;
msg.obj = res;
mHandler.sendMessage(msg);
}
@Override
public void onFailure(Call call, IOException e) {
}
});
}
/**
* 事件捕获
*/
class MHandler extends Handler {
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
switch (msg.what) {
case MSG_GOODS_OK:
if (msg.obj != null) {
// 获取传递过来的JSON数据vlResult
String vlResult = (String) msg.obj;
// 解析获取的JSON数据vlResult,并将解析后的数据存放在集合goodsInfos中
List<GoodsInfo> goodsInfos = getGoodsList(vlResult);
// 将集合goodsInfos设置到数据适配器的对象adapter中
adapter.setData(goodsInfos);
}
break;
}
}
}
public List<GoodsInfo> getGoodsList(String json) {
Gson gson = new Gson(); // 使用gson库解析JSON数据
// 创建一个TypeToken的匿名子类对象,并调用对象的getType()方法
Type listType = new TypeToken<List<GoodsInfo>>() {
}.getType();
// 把获取到的集合数据存放到goodsInfos中
List<GoodsInfo> goodsInfos = gson.fromJson(json, listType);
return goodsInfos;
}
}
3.4 安装配置Tomcat服务器
Tomcat运行稳定、可靠、效率高,不仅可以和目前大部分主流的Web服务器(如Apache、IIS服务器)一起工作,还可以作为独立的Web服务器软件。
1.下载Tomcat
在Tomcat官网上下载apache-tomcat-8.5.59-windows-x64.zip文件,解压该文件可以看到Tomcat的目录结构,如下图所示。
2. 启动Tomcat
在Tomcat安装目录的bin目录下,存放了许多脚本文件,其中startup.bat就是启动Tomcat的脚本文件,如下图所示。
双击startup.bat文件,便会启动Tomcat服务器,Tomcat启动信息窗口如下图所示。
Tomcat服务器启动后,在浏览器的地址栏中输入http://localhost:8080访问Tomcat服务器,如果浏览器中的显示Tomcat页面如下图所示,则说明Tomcat 服务器安装部署成功了。
3. 关闭Tomcat
在Tomcat根目录下的bin文件夹中,运行shutdown.bat脚本文件即可关闭Tomcat或者直接关闭Tomcat启动信息窗口。
四、Handler消息机制
目标
- 熟悉Handler消息机制的概述,能够归纳Handler消息机制的原理
Handler是一种异步回调机制,主要负责与子线程进行通信。
Handler机制主要包括四个关键对象:
-
Message
:是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。 -
Handler
:是处理者的意思,它主要用于发送消息和处理消息。 -
MessageQueue
:是消息队列的意思,它主要用来存放通过Handler发送的消息。通过Handler发送的消息会存在MessageQueue中等待处理,每个线程中只会有一个MessageQueue对象。 -
Looper
:是每个线程中的MessageQueue的管家。调用Looper的loop()方法后,就会进入到一个无限循环中。每当发现MessageQueue中存在一条消息,就会将它取出,并传递到Handler的handleMessage()方法中。文章来源:https://www.toymoban.com/news/detail-487174.html
文章来源地址https://www.toymoban.com/news/detail-487174.html
到了这里,关于CH9-网络编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!