
正文
Android开发9:网络访问&Web服务开发
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
前言
啦啦啦各位小伙伴们好~
一起进入我们今天的主题。今天我们将和大家学习网络访问和Web服务开发的相关知识,一起学习熟练使用 HttpURLConnection 访问 WebService,熟悉使用多线程以及 Handler 更新 UI,熟悉使用 XmlPullParser 解析 xml 文档数据,了解 RecyclerView 控件的使用。
基础知识一、网络访问&Web服务开发
1 、实验WebService 地址
(1)实验中所使用的 WebService 地址为:http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?op=getWeather
在浏览器打开实验需要的 WebService 网站可以看到截图如下:

可以看到,查询需要用到两个参数 theCityCode(默认参数为上海)和 theUserID,如果使用免费的 WebService,其中 theUserID 置空即可,输入后点击调用,查看返回值:

可以看到其中返回的数据为 xml 文件格式,我们需要用 XmlPullParser 提取我们需要的信息。
(2)有兴趣可以在网站上看一下如何免费使用 WebService:http://www.webxml.com.cn/zh_cn/web_services.aspx
PS:免费用户 24 小时内查询不超过 50 次并且获取二次数据大于间隔 600ms
(如果测试时超过上限更换一下网络 IP 重新测试即可)
2 、网络访问
在本次实验中使用 HttpURLConnection 实现网络访问:
(1) 在 manifest 中添加网络访问权限:

(2) 判断是否有可用网络:使用 ConnectivityManager 获取手机所有连接管理对象,使用 manager 获取 NetworkInfo 对象,最后判断当前网络状态是否为连接状态即可。
(3) 定义我们需要用到的 WebService 地址:

(4) 使用 HttpURLConnection 新建一个 http 连接,新建一个 URL 对象,打开连接即可,并且设置访问方法以及时间设置:

(5)将我们需要请求的字段以流的形式写入 connection 之中,这一步相当于将需要的参数提交到网络连接,并且请求网络数据(类似于 html 中的表单操作,将 post 数据提交到服务器)

(6)网页获取 xml 转化为字符串:

在 logcat 中查看一下 response,实际上就是将网站上的 xml 转化为 string 而已,便于下一步的 xml 数据解析

(7)关闭 connection:

(8)注:Android4.0 之后,http 请求需要开启子线程,然后由子线程执行请求,所以我们之前所写代码都是在子线程中完成的,并且使用 XmlPullParser 进行解析从而得到我们想要的数据:

3 、Handler 更新 UI
在之前的实验中我们已经知道,子线程中不能直接修改 UI 界面,需要中间人 handler 进行UI 界面的修改:

Message 消息机制:负责在不同的线程之间进行交互处理,我们先定义消息类型:

然后将我们需要的内容通过消息传递回来:

4 、XmlPullParser 解析 xml 文档
首先获取 XmlPullParser 对象实例,然后设置需要解析的字符串,最后按照 tag 逐个获取所需要的 string:


注:
由于我们获取的 xml 字符串是 string 类型的数组(ArrayofString),所以我们也可以将按照 string(Tag)获取的字符串储存到ArrayList<String>中,然后在 Handler 中再进行处理,不断的将所需要的字符串进行分割处理,以用来更新 UI 界面。
异常处理部分:
1)城市名输入错误时:注意判断取回的字符串是否是“查询结果为空。…”
2)二次查询间隔<600ms 时:注意判断取回的字符串是否是“发现错误:免费用户不能使用高速访问。…”

3)达到上限 50 次:注意判断取回的字符串是否是“发现错误:免费用户 24 小时内访问超过规定数量。…”

二 、RecyclerView 控件使用
RecyclerView 是 support-v7 包中的新组件,是一个强大的滑动组件,与经典的 ListView相比,同样拥有 item 回收复用的功能。RecyclerView 是 ListView 的升级版,最为突出的就是其拓展性极强,并且灵活性高。
(1)导入 RecyclerView 的 jar包,导入方法:
http://jingyan.baidu.com/article/e6c8503c7190b7e54f1a1893.html
(2) RecylerView 的设置

(3)Adapter 的构造:
package com.example.administrator.ex9;
import java.util.ArrayList;
import java.util.List;
import android.R.integer;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class WeatherAdapter extends RecyclerView.Adapter<WeatherAdapter.ViewHolder>{
private ArrayList<Weather> weather_list;
private LayoutInflater mInflater;
public interface OnItemClickLitener
{
void onItemClick(View view, int position,Weather item);
}
private OnItemClickLitener mOnItemClickLitener;
public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener)
{
this. mOnItemClickLitener = mOnItemClickLitener;
}
public WeatherAdapter(Context context,ArrayList<Weather> items) {
super();
weather_list = items;
mInflater = LayoutInflater.from(context);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = mInflater.inflate(R.layout. weather_item, viewGroup, false);
ViewHolder holder = new ViewHolder(view);
holder. Date = (TextView)view.findViewById(R.id. date);
holder. Weather_description =(TextView)view.findViewById(R.id. weather_description);
holder. Temperature = (TextView)view.findViewById(R.id. temperature);
return holder;
}
@Override
public void onBindViewHolder( final ViewHolder viewHolder, final int i) {
viewHolder. Date.setText( weather_list.get(i).getDate());
viewHolder. Weather_description.setText( weather_list.get(i).getWeather_description());
viewHolder. Temperature.setText( weather_list.get(i).getTemperature());
if ( mOnItemClickLitener != null)
{
viewHolder. itemView.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto- - generated method stub
mOnItemClickLitener.onItemClick(viewHolder. itemView, i, weather_list.get(i));
}
});
}
}
@Override
public int getItemCount() {
return weather_list.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
public ViewHolder(View itemView) {
super(itemView);
}
TextView Date;
TextView Weather_description;
TextView Temperature;
}
}
(3) Handler 中得到 weather_list 之后,绑定 adpter:

实验内容
实现一个简单的天气查询应用,具体要求如下:
1)该界面为应用启动之后的主界面 2)点击 Search 按钮后(若网络不可用)

3)输入城市名 Search(网络可用且城市名正确) 4)输入城市名 Search(城市名不正确)

5)快速点击按钮(二次查询<600ms) 6)查询达到上限 50 次

实验过程
本次实验主要是实现一个简单的天气查询应用,实现天气查询的功能。本次实验主要涉及使用 HttpURLConnection 访问 WebService,使用多线程以及Handler 更新 UI,熟悉使用 XmlPullParser 解析 xml 文档数据,了解RecyclerView 控件的使用。首先,写好界面的 XML 布局文件。这里我们需要设置一个 EditText 和一个搜索 Button,并在一个以@drawable/shape 为背景的 LinearLayout 中嵌套几个LinearLayout 以显示不同的数据,再往下设置一个 ListView 显示天气的详细内容,最后设置一个RecyclerView来显示接下来五天的天气概况。listview的item界面布局中设置两个 TextView,RecyclerView 的 item 界面布局中设置三个TextView。背景 shape 如下:

接下来完成 MainActivity.java 类,在类中我们将使用 HttpURLConnection实现网络访问。在初始化控件后,在 manifest 中添加网络访问权限:

定义我们需要用到的 WebService 地址:

然后判断是否有可用网络。这里使用 ConnectivityManager 获取手机所有连接管理对象,使用 manager 获取 NetworkInfo 对象,最后判断当前网络状态是否为连接状态(写到 search 按钮事件中):

在按钮事件中,我们还需要利用设置好的时间参数,用判断语句判断两次查询间隔是否小于 600ms 以及查询栏输入是否为空:

http 请求需要开启子线程 ,然 后由 子 线程执 行请 求, 并且使用XmlPullParser 进行解析从而得到我们想要的数据:

在子线程中,使用 HttpURLConnection 新建一个 http 连接,新建一个 URL对象,打开连接即可,并且设置访问方法以及时间设置:

将我们需要请求的字段以流的形式写入 connection 之中,这一步相当于将需要的参数提交到网络连接,并且请求网络数据:

网页获取 xml 转化为字符串:

在子线程中使用 Message 消息机制,以实现在不同的线程之间进行交互处理。在定义消息类型后,将我们需要的内容通过消息传递回来:

然后关闭 connection:

在子线程执行完请求之后,XmlPullParser 解析 xml 文档,首先获取XmlPullParser 对象实例,然后设置需要解析的字符串,最后按照 tag 逐个获取所需要的 string:

然后使用Handler 进行更新,子线程中不能直接修改 UI 界面,需要 handler进行 UI 界面的修改:

更新 Toast 的产生:

更新城市名和更新时间信息(由于我们获取的 xml 字符串是 string 类型的数组(ArrayofString),所以我们也可以将按照 string(Tag)获取的字符串储存到 ArrayList<String>中,然后在 Handler 中再进行处理):

在取有背景色的文本框所包含的数据时 , 我们需要 Java 中的StringTokenizer 类不断的将所需要的字符串进行分割处理,以用来更新 UI 界面。
StringTokenizer 是字符串分隔解析类型,属于:Java.util 包。在 StringTokenizer 中,所有方法均为 public,书写格式为:[修饰符] <返回类型><方法名([参数列表])>——
int countTokens():返回 nextToken 方法被调用的次数。
boolean hasMoreTokens():返回是否还有分隔符。
boolean hasMoreElements():返回是否还有分隔符。
String nextToken():返回从当前位置到下一个分隔符的字符串。
Object nextElement():返回从当前位置到下一个分隔符的字符串。
String nextToken(String delim):与 4 类似,以指定的分隔符返回结果。
则可以分割其中的数据来更新 UI 界面:

在更新 ListView 中的信息时,我们还是需要使用键值对来保存数据:

接下来完成拓展内容 RecyclerView 控件使用。
RecyclerView 是 support-v7 包中的新组件,是一个强大的滑动组件,与经典的 ListView 相比,同样拥有 item 回收复用的功能。RecyclerView 是ListView 的升级版,最为突出的就是其拓展性极强,并且灵活性高。在导入 RecyclerView 的 jar 包后,对 RecylerView 进行设置:

按照文档中的要求设置好适配器 WeatherAdapter,并在 Weather 类中存储相应的数据:

更新 recyclerView 中的信息时,按照 string(Tag)获取字符串:

并且设置三个字符串组将五天的天气信息添加到其中:

按照顺序将五天的信息添加进 weather_list 中去:

Handler 中得到 weather_list 之后,绑定 adpter:

完成实验~
实验截图



其他总结
WebService:
WebService 是发布在网络上的 API,可以通过发送 XML 调用,WebService返回结果也是 XML 数据。
Android 开发过程中为什么要多线程:
我们创建的 Service、Activity 以及 Broadcast 均是一个主线程处理,这里我们可以理解为 UI 线程。但是在操作一些耗时操作时,比如 I/O 读写的大文件读写,数据库操作以及网络下载需要很长时间,为了不阻塞用户界面,出现 ANR的响应提示窗口,这个时候我们可以考虑使用 Thread 线程来解决。
实验中我们还使用多线程以及 Handler 更新 UI。
使用 Handler 更新 UI 的原因:
(1)如果当前线程和主线程不相等的话,更新 UI 就会抛出异常;
(2)Activity 检查当前线程和主线程是否相等是在 onResume()方法才
开始的;
(3)所以在新开启的线程,如果不休眠直接更新 UI 的话不会抛出异常;
(4)如果休眠再做更新 UI 操作的话就会抛出异常。
源码下载
源码下载点击这里~
注
1、本实验实验环境:
操作系统 Windows 10
实验软件 Android Studio 2.2.1
虚拟设备:Nexus_5X
API:23
2、贴代码的时候由于插入代码框的大小问题,代码格式不太严整,望见谅~
Android开发9:网络访问&Web服务开发的更多相关文章- 客户通过新型网络访问Web服务
- 大规模web服务开发技术
大规模web服务开发技术 总评 这本书是日本一个叫hatena的大型网站的CTO写的,通过hatena网站从小到大的演进来反应一个web系统从小到大过程中的各种系统和技术架构变迁,比较接 ...
- 《大规模web服务开发技术》笔记
前段时间趁空把<大规模web服务开发技术>这本书看完了,今天用一下午时间重新翻了一遍,把其中的要点记了下来,权当复习和备忘.由于自己对数据压缩.全文检索等还算比较熟,所以笔记内容主要涉及前 ...
- 大规模web 服务开发技术
<大规模web 服务开发技术> 是一本讲解大型Web 应用的入门级书籍,能够让我们接触到大应用的知识点. 目录如下: 第1章 大规模Web服务的开发定位——掌握整体第2章 大规模数据处 ...
- 《大规模Web服务开发技术》
Web 服务开发的心灵鸡汤 周末去上海陪妹子的两天在路途上看完了这本<大规模 Web 服务开发技术>. <大规模 Web 服务开发技术>是日本的 Hetena 团队以夏天举办的 ...
- 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)
目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构 前言 学习Python也有一个半月时间了,学到现在感觉 ...
- Reporting Service编程----访问Web服务
将报表服务器 Web 服务的引用添加到项目中后,下一步是创建 Web 服务代理类的实例. 然后,您可以通过调用代理类中的方法来访问 Web 服务的方法. 当你的应用程序调用这些方法时,代理类生成的代码 ...
- 在Android开发中调用Rest web服务(转)
首先从维基百科上拷贝一点Rest的基本概念给大家看看,然后我们再开始详解在Android中如何调用Rest服务.表象化状态转变(英文:Representational State Transfer,简 ...
- iOS开发25:使用SOAP访问Web服务
SOAP是简单对象访问协议,它可看成是HTTP与XML的结合,其中XML部分是作为HTTP报文的实体主体部分.具体信息可以参考百度百科. 在iOS中使用SOAP,需要我们自己组装XML格式的字符串,当 ...
随机推荐- ArcGIS API for JavaScript(2)-ArcGIS Server发布要素图层服务
1.前言 上一篇该系列的文章我们主要讲了一下基础Web地图搭建,这篇我们主要讲一下ArcGIS Server发布服务,并且如何调用服务.将自己的数据加载到Web地图当中来,实现Web端浏览数据. 2. ...
- 解决Linux性能问题的前60秒
为了解决性能问题,你登入了一台Linux服务器,在最开始的一分钟内需要查看什么? 在Netflix我们有一个庞大的EC2 Linux集群,还有非常多的性能分析工具来监控和调查它的性能.其中包括用于云监 ...
- thinkphp中limit方法
limit方法也是模型类的连贯操作方法之一,主要用于指定查询和操作的数量,特别在分页查询的时候使用较多.ThinkPHP的limit方法可以兼容所有的数据库驱动类的. 用法 限制结果数量 例如获取满足 ...
- Oracle 如何对时间进行简单加减运算
在我们用dbms_job包进行定时Job的时候,需要设置时间间隔,所以需要知道时间的基本加减方法. SQL> alter session set nls_date_format='yyyy-mm ...
- JavaScript之数据类型讲解
JavaScript中有5种简单数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String.还有1种复杂数据类型——Object,Object本质上是由一 ...
- p45.asm
; ========================================== ; pmtest3.asm ; 编译方法:nasm pmtest3.asm -o pmtest3.com ; ...
- 使用PullToRefresh实现下拉刷新和上拉加载
使用PullToRefresh实现下拉刷新和上拉加载 分类: Android2013-12-20 15:51 78158人阅读 评论(91) 收藏 举报 Android下拉刷新上拉加载PullToRe ...
- PHP脚本实现凯撒加(解)密
原文:PHP脚本实现凯撒加(解)密 今天在看某ctf时候遇到一题凯撒加密的题,然后看到write up里有这样一句 顿时感觉这题目有点坑啊,这要不写个脚本来跑要推到啥时候啊,于是又了本文: <? ...
- spring Cloud 域名映射 ip地址实现
spring.cloud.inetutils.preferredNetworks[0]=^192\.168 eureka.instance.prefer-ip-address=true
- selenium的三种等待方式
selenium有三种等待方式 1.time.sleep() 设置等待最简单的方法就是强制等待,但一般不建议使用,可以在调试的时候进行使用 2.隐性等待 driver.implictily_wait( ...
大规模web服务开发技术 总评 这本书是日本一个叫hatena的大型网站的CTO写的,通过hatena网站从小到大的演进来反应一个web系统从小到大过程中的各种系统和技术架构变迁,比较接 ...
前段时间趁空把<大规模web服务开发技术>这本书看完了,今天用一下午时间重新翻了一遍,把其中的要点记了下来,权当复习和备忘.由于自己对数据压缩.全文检索等还算比较熟,所以笔记内容主要涉及前 ...
<大规模web 服务开发技术> 是一本讲解大型Web 应用的入门级书籍,能够让我们接触到大应用的知识点. 目录如下: 第1章 大规模Web服务的开发定位——掌握整体第2章 大规模数据处 ...
Web 服务开发的心灵鸡汤 周末去上海陪妹子的两天在路途上看完了这本<大规模 Web 服务开发技术>. <大规模 Web 服务开发技术>是日本的 Hetena 团队以夏天举办的 ...
目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构 前言 学习Python也有一个半月时间了,学到现在感觉 ...
将报表服务器 Web 服务的引用添加到项目中后,下一步是创建 Web 服务代理类的实例. 然后,您可以通过调用代理类中的方法来访问 Web 服务的方法. 当你的应用程序调用这些方法时,代理类生成的代码 ...
首先从维基百科上拷贝一点Rest的基本概念给大家看看,然后我们再开始详解在Android中如何调用Rest服务.表象化状态转变(英文:Representational State Transfer,简 ...
SOAP是简单对象访问协议,它可看成是HTTP与XML的结合,其中XML部分是作为HTTP报文的实体主体部分.具体信息可以参考百度百科. 在iOS中使用SOAP,需要我们自己组装XML格式的字符串,当 ...
- ArcGIS API for JavaScript(2)-ArcGIS Server发布要素图层服务
1.前言 上一篇该系列的文章我们主要讲了一下基础Web地图搭建,这篇我们主要讲一下ArcGIS Server发布服务,并且如何调用服务.将自己的数据加载到Web地图当中来,实现Web端浏览数据. 2. ...
- 解决Linux性能问题的前60秒
为了解决性能问题,你登入了一台Linux服务器,在最开始的一分钟内需要查看什么? 在Netflix我们有一个庞大的EC2 Linux集群,还有非常多的性能分析工具来监控和调查它的性能.其中包括用于云监 ...
- thinkphp中limit方法
limit方法也是模型类的连贯操作方法之一,主要用于指定查询和操作的数量,特别在分页查询的时候使用较多.ThinkPHP的limit方法可以兼容所有的数据库驱动类的. 用法 限制结果数量 例如获取满足 ...
- Oracle 如何对时间进行简单加减运算
在我们用dbms_job包进行定时Job的时候,需要设置时间间隔,所以需要知道时间的基本加减方法. SQL> alter session set nls_date_format='yyyy-mm ...
- JavaScript之数据类型讲解
JavaScript中有5种简单数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String.还有1种复杂数据类型——Object,Object本质上是由一 ...
- p45.asm
; ========================================== ; pmtest3.asm ; 编译方法:nasm pmtest3.asm -o pmtest3.com ; ...
- 使用PullToRefresh实现下拉刷新和上拉加载
使用PullToRefresh实现下拉刷新和上拉加载 分类: Android2013-12-20 15:51 78158人阅读 评论(91) 收藏 举报 Android下拉刷新上拉加载PullToRe ...
- PHP脚本实现凯撒加(解)密
原文:PHP脚本实现凯撒加(解)密 今天在看某ctf时候遇到一题凯撒加密的题,然后看到write up里有这样一句 顿时感觉这题目有点坑啊,这要不写个脚本来跑要推到啥时候啊,于是又了本文: <? ...
- spring Cloud 域名映射 ip地址实现
spring.cloud.inetutils.preferredNetworks[0]=^192\.168 eureka.instance.prefer-ip-address=true
- selenium的三种等待方式
selenium有三种等待方式 1.time.sleep() 设置等待最简单的方法就是强制等待,但一般不建议使用,可以在调试的时候进行使用 2.隐性等待 driver.implictily_wait( ...






