前言

  啦啦啦各位小伙伴们好~

  一起进入我们今天的主题。今天我们将和大家学习网络访问和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服务开发的更多相关文章

  1. 客户通过新型网络访问Web服务

  2. 大规模web服务开发技术

    大规模web服务开发技术 总评        这本书是日本一个叫hatena的大型网站的CTO写的,通过hatena网站从小到大的演进来反应一个web系统从小到大过程中的各种系统和技术架构变迁,比较接 ...

  3. 《大规模web服务开发技术》笔记

    前段时间趁空把<大规模web服务开发技术>这本书看完了,今天用一下午时间重新翻了一遍,把其中的要点记了下来,权当复习和备忘.由于自己对数据压缩.全文检索等还算比较熟,所以笔记内容主要涉及前 ...

  4. 大规模web 服务开发技术

    <大规模web 服务开发技术> 是一本讲解大型Web 应用的入门级书籍,能够让我们接触到大应用的知识点. 目录如下: 第1章  大规模Web服务的开发定位——掌握整体第2章  大规模数据处 ...

  5. 《大规模Web服务开发技术》

    Web 服务开发的心灵鸡汤 周末去上海陪妹子的两天在路途上看完了这本<大规模 Web 服务开发技术>. <大规模 Web 服务开发技术>是日本的 Hetena 团队以夏天举办的 ...

  6. 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)

    目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构   前言 学习Python也有一个半月时间了,学到现在感觉 ...

  7. Reporting Service编程----访问Web服务

    将报表服务器 Web 服务的引用添加到项目中后,下一步是创建 Web 服务代理类的实例. 然后,您可以通过调用代理类中的方法来访问 Web 服务的方法. 当你的应用程序调用这些方法时,代理类生成的代码 ...

  8. 在Android开发中调用Rest web服务(转)

    首先从维基百科上拷贝一点Rest的基本概念给大家看看,然后我们再开始详解在Android中如何调用Rest服务.表象化状态转变(英文:Representational State Transfer,简 ...

  9. iOS开发25:使用SOAP访问Web服务

    SOAP是简单对象访问协议,它可看成是HTTP与XML的结合,其中XML部分是作为HTTP报文的实体主体部分.具体信息可以参考百度百科. 在iOS中使用SOAP,需要我们自己组装XML格式的字符串,当 ...

随机推荐

  1. sql2000数据库误删除后自行恢复二次覆盖成功恢复

    sql2000数据库误删除后自行恢复二次覆盖成功恢复 [数据恢复故障描述] 今天接到一个客户电话,他的速达sql2000数据库,数据库误删除了,关键之前还没有备份过.他就想自己尝试恢复,使用网上下载的 ...

  2. Java数据结构整理(一)

    ava数据结构内容整理关键字: 数据结构 Collection:List.SetMap:HashMap.HashTable如何在它们之间选择一.Array , ArraysJava所有“存储及随机访问 ...

  3. Prism之使用EventAggregation进行模块间通信

    在开发Silverlight程序的时候,经常需要在不同的组件间进行通信.比如点击一个button,可能就需要改变另一个控件的内容.比较直接的办法是使用事件,当然使用MVVM的时候也可以使用comman ...

  4. ajax 跨域了 cors

    <?php /** * Author: humanhuang * Date: 13-12-17 */ header('Access-Control-Allow-Origin:*'); heade ...

  5. 动态创建Fastreport(delphi)

    动态创建Fastreport分以下几个步骤: 1.首先清空Fastreport,定义全局变量,并加载数据集    frReport.Clear;    frReport.DataSets.Add(fr ...

  6. ios 清除列表选中状态

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

  7. 用JS添加文本框案例代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. iOS 准备

    iOS 编程知识点 iOS 基础知识点 iOS 之 系统机制 Xcode 使用技巧 Mac 使用技巧 iOS 之 英语 iOS 之 编外知识点 iOS 知识库链接

  9. 第一个shell脚本 结合计划任务下载远程文件

    思路: 进入/usr/local/apache2/htdocs/ipa/  循环读取 /root/shell/wget/down.txt  每次一行,每一行直接就是一条命令,直接 $line 就可以执 ...

  10. jQuery 的 ready 函数是如何工作的?(源码分析)

    如果你使用过 jQuery , 就必然使用过 ready 函数,它用来注册当页面准备好之后可以执行的函数. 问题来啦,我们的页面什么时候准备好了呢? 1. onload 事件 最基本的处理方式就是页面 ...