一步步教你为网站开发Android客户端

<div align="left">

本文面向Android初级开发者,有一定的Java和Android知识即可。

</div>
<div align="left">文章覆盖知识点:HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新ListView</div>
<div align="left">背景介绍:客户端(Client)或称为用户端,是指与服务器相对应,为客户提供本地服务的程序。而android 系统上的90%客户端软件都有一个共性,就是为了改善网页在android系统上体验不佳而生,最具有影响力的软件有:新浪微博、人人网、淘宝等,这类软 件最突出的特点就是,先有网站再有软件。由于网络技术发展的多样性,手机浏览器往往无法跟随它的步伐,为改善用户体验,网站客户端软件印运而生。</div>
<div align="left">以下内容100%原创,并在<a href="http://www.apkbus.com/" target="_blank">安卓</a>巴士论坛首发,如需转载,请注明作者和出处。谢谢合作。</div>
<div align="left">

开发Android网站客户端通常有两种方法:第一种,通过服务端的开放平台,调用提供的API接口来开发,比如说open sina;第二种,服务端没有提供任何接口,你也没有服务端任何数据库访问权限,就是一个纯纯粹粹的网站,要你做客户端。今天,我要和大家分享的正是第二 种情况。

</div>
<div align="center"></div>
这是一个简单的示意图,告诉我们,数据是由网页从数据库中取出,我们要为这个系统做客户端,我们就应该这样去改造它。
<div align="center"></div>
<div align="left">通过这样间接的方法来访问数据库,只要网页能看到的内容,我们的客户端都能获取到,而UI是由你自行制作,就可以使使用体验上一个台阶。</div>
<div align="left">

既然网页是我们的数据枢纽,我们就从网页分析着手。

</div>
<div align="left">该教程来自本人项目-掌上民大-真实经验,所以用项目中的”掌上图书馆”板块来示范。</div>
<div align="left">该项目任务为中南民族大学图书馆图书查询功能制作客户端。</div>
<div align="left">

首先打开该网址<a href="http://www.lib.scuec.edu.cn/" target="_blank">http://www.lib.scuec.edu.cn/</a>,我们会看到主界面

</div>
<div align="center"></div>
<div align="left">

正中间就是查询入口,我们输入”android”进行查询

</div>
<div align="center"></div>
<div align="left">得到结果的网页,但我们能发现,这个页面是ILAS图书管理系统,所以真正的入口并不是上面红圈的地方。
所以我继续找,经过短暂的观察,发现入口在这里</div>
<div align="center">&lt;ignore_js_op&gt;</div>
<div align="left">

我们点击进入

</div>
<div align="center"></div>
<div align="left">

果然就是这货,我们点击书目查询

</div>
<div align="center"></div>
<div align="left">

就是它了。真正的入口就在这里,这时我们打开HttpWatch软件,点”Record”,在搜索框里输入”android”,点击查询,抓取以”android”为关键字搜索时浏览器的所有包。待结果界面载入完成后,HttpWatch上就会出现如下信息

</div>
<div align="center"></div>
我们先看Summary选项卡,我们可以初步了解,这是一个POST请求(Http请求中的一种,另一种是GET),POST到的网址是<a href="http://coin.lib.scuec.edu.cn/cgi-bin/IlaswebBib" target="_blank">http://coin.lib.scuec.edu.cn/cgi-bin/IlaswebBib</a>。
这样我们的思路就清晰了,我们的客户端需要模拟浏览器,向上述地址POST一个包,那个地址肯定会返回一个Content给我们,不出意外的话,Content里面就是我们要的书目信息。那么,浏览器POST上去的内容是什么呢?我们点击这条POST请求,看详细信息,
<div align="center"></div>
由于是POST请求,我们先看POST DATA,里面是以键值对的形式存储的,这里显示了我们浏览器在我们搜索”android”时,POST的所有数据。那这些键值对又代表了什么呢,我们打开这个网页的源码来一探究竟。
<div align="center"></div>
从这段可以看出v_index是表示查找途径的它有TITLE,AUTHOR,SUBJECT,CLASSNO,ISBN,CALLNO六种值
<div align="center"></div>
FLD_DAT_BEG和FLD_DAT_END分别是开始和结束年份
<div align="center"></div>
v_value表示用户在搜索框中输入的内容
<div align="center"></div>
v_paggnum表示每页显示的书目条数,有10 15 20三种
<div align="center"></div>
v_seldatabases是检索库  有0 1 2三种值v_LogicSrch是检索方式   有0 1两种值
<div align="center"></div>
Submit是查询或重填,有 查 询 和 重 填 两种值

至此,我们弄清楚了POST Data里所有内容的含义和取值可能。但我们模拟POST请求为什么,其实就是为了得到搜索的书目信息,所以我们看一下返回的Content是不是我们要的东西
<div align="center"></div>
果然,就是我们搜到的书目信息,就以String的形式放在Content里面。最后我们查看一下Stream,截图,以防等下我们需要这里面的东西
<div align="center"></div>
好了,这个页面的工作原理我们已经弄清楚了:用户在网页中输入搜索内容后,点击查询,浏览器会POST一个Data到目标网址,该网址的返回信息就是搜到的书目。
我们开始编写代码,模拟这个过程,先打开eclipse建立一个Java项目(注意是Java项目,因为Java项目可以完美移植到Android项目中且调试方便,并且模拟Http请求这一过程没有用到任何Android功能)。
导入HttpClient的4个包commons-codec、commons-httpclient、commons-logging、log4j。
<div data-settings=" minimize scroll-mouseover">
<div><textarea readonly="readonly" wrap="off" data-settings="dblclick">//实例化HttpClient
HttpClient client = new HttpClient();
//Stream页面里面有Host地址 端口是80
client.getHostConfiguration().setHost("http://coin.lib.scuec.edu.cn", 80);
//用目标地址 实例一个POST方法
PostMethod post = new PostMethod("http://coin.lib.scuec.edu.cn/cgi-bin/IlaswebBib");
//将需要的键值对写出来
NameValuePair beg = new NameValuePair("FLD_DAT_BEG" , “”);
NameValuePair end = new NameValuePair("FLD_DAT_END" , “”);
NameValuePair submit = new NameValuePair("submit" , "查&amp;nbsp;询"));
NameValuePair vIndex = new NameValuePair("v_index" , “TITLE”);
NameValuePair vLogicSrch = new NameValuePair("v_LogicSrch" , "0");
NameValuePair vPagenum = new NameValuePair("v_pagenum" , "10");
NameValuePair vSeldatabase = new NameValuePair("v_seldatabase" , "0");
NameValuePair vValue = new NameValuePair("v_value" ,”android”);

//给POST方法加入上述键值对
post.setRequestBody(new NameValuePair[] {beg , end , submit , vIndex , vLogicSrch , vPagenum , vSeldatabase , vValue});
//执行POST方法
client.executeMethod(post);
//将POST返回的数据以流的形式读入,再把输入流流至一个buff缓冲字节数组
//StreamTool类是我自己写的一个工具类,其内容将在下文附出
byte[] buff = StreamTool.readInputStream(post.getResponseBodyAsStream());
//将返回的内容格式化为String存在html中
String html = new String(buff);
//任务完成了,释放连接
post.releaseConnection();</textarea></div>
<div>
<table>
<tbody>
<tr>
<td data-settings="show">
<div>
<div data-line="crayon-512482090f24d-1">1</div>
<div data-line="crayon-512482090f24d-2">2</div>
<div data-line="crayon-512482090f24d-3">3</div>
<div data-line="crayon-512482090f24d-4">4</div>
<div data-line="crayon-512482090f24d-5">5</div>
<div data-line="crayon-512482090f24d-6">6</div>
<div data-line="crayon-512482090f24d-7">7</div>
<div data-line="crayon-512482090f24d-8">8</div>
<div data-line="crayon-512482090f24d-9">9</div>
<div data-line="crayon-512482090f24d-10">10</div>
<div data-line="crayon-512482090f24d-11">11</div>
<div data-line="crayon-512482090f24d-12">12</div>
<div data-line="crayon-512482090f24d-13">13</div>
<div data-line="crayon-512482090f24d-14">14</div>
<div data-line="crayon-512482090f24d-15">15</div>
<div data-line="crayon-512482090f24d-16">16</div>
<div data-line="crayon-512482090f24d-17">17</div>
<div data-line="crayon-512482090f24d-18">18</div>
<div data-line="crayon-512482090f24d-19">19</div>
<div data-line="crayon-512482090f24d-20">20</div>
<div data-line="crayon-512482090f24d-21">21</div>
<div data-line="crayon-512482090f24d-22">22</div>
<div data-line="crayon-512482090f24d-23">23</div>
<div data-line="crayon-512482090f24d-24">24</div>
<div data-line="crayon-512482090f24d-25">25</div>
<div data-line="crayon-512482090f24d-26">26</div>
<div data-line="crayon-512482090f24d-27">27</div>
</div></td>
<td>
<div>
<div>//实例化HttpClient</div>
<div>HttpClient client = new HttpClient();</div>
<div>//Stream页面里面有Host地址 端口是80</div>
<div>client.getHostConfiguration().setHost("http://coin.lib.scuec.edu.cn", 80);</div>
<div>//用目标地址 实例一个POST方法</div>
<div>PostMethod post = new PostMethod("http://coin.lib.scuec.edu.cn/cgi-bin/IlaswebBib");</div>
<div>//将需要的键值对写出来</div>
<div>NameValuePair beg = new NameValuePair("FLD_DAT_BEG" , “”);</div>
<div>NameValuePair end = new NameValuePair("FLD_DAT_END" , “”);</div>
<div>NameValuePair submit = new NameValuePair("submit" , "查&amp;nbsp;询"));</div>
<div>NameValuePair vIndex = new NameValuePair("v_index" , “TITLE”);</div>
<div>NameValuePair vLogicSrch = new NameValuePair("v_LogicSrch" , "0");</div>
<div>NameValuePair vPagenum = new NameValuePair("v_pagenum" , "10");</div>
<div>NameValuePair vSeldatabase = new NameValuePair("v_seldatabase" , "0");</div>
<div>NameValuePair vValue = new NameValuePair("v_value" ,”android”);</div>
<div></div>
<div>//给POST方法加入上述键值对</div>
<div>post.setRequestBody(new NameValuePair[] {beg , end , submit , vIndex , vLogicSrch , vPagenum , vSeldatabase , vValue});</div>
<div>//执行POST方法</div>
<div>client.executeMethod(post);</div>
<div>//将POST返回的数据以流的形式读入,再把输入流流至一个buff缓冲字节数组</div>
<div>//StreamTool类是我自己写的一个工具类,其内容将在下文附出</div>
<div>byte[] buff = StreamTool.readInputStream(post.getResponseBodyAsStream());</div>
<div>//将返回的内容格式化为String存在html中</div>
<div>String html = new String(buff);</div>
<div>//任务完成了,释放连接</div>
<div>post.releaseConnection();</div>
</div></td>
</tr>
</tbody>
</table>
</div>
</div>
<div data-settings=" minimize scroll-mouseover">
<div><textarea readonly="readonly" wrap="off" data-settings="dblclick">//StreamTool类如下
public class StreamTool {
/**
* 从输入流中获取数据
* @param inputStream 输入流
* @return 字节数组
* @throws Exception
*/
public static byte[] readInputStream(InputStream inputStream) throws Exception
{
//实例化一个输出流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//一个1024字节的缓冲字节数组
byte[] buffer = new byte[1024];
int len = 0;
//读流的基本知识
while ((len=inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
//用完要关,大家都懂的
inputStream.close();
return outputStream.toByteArray();
}
}</textarea></div>
<div>
<table>
<tbody>
<tr>
<td data-settings="show">
<div>
<div data-line="crayon-512482090f2c4-1">1</div>
<div data-line="crayon-512482090f2c4-2">2</div>
<div data-line="crayon-512482090f2c4-3">3</div>
<div data-line="crayon-512482090f2c4-4">4</div>
<div data-line="crayon-512482090f2c4-5">5</div>
<div data-line="crayon-512482090f2c4-6">6</div>
<div data-line="crayon-512482090f2c4-7">7</div>
<div data-line="crayon-512482090f2c4-8">8</div>
<div data-line="crayon-512482090f2c4-9">9</div>
<div data-line="crayon-512482090f2c4-10">10</div>
<div data-line="crayon-512482090f2c4-11">11</div>
<div data-line="crayon-512482090f2c4-12">12</div>
<div data-line="crayon-512482090f2c4-13">13</div>
<div data-line="crayon-512482090f2c4-14">14</div>
<div data-line="crayon-512482090f2c4-15">15</div>
<div data-line="crayon-512482090f2c4-16">16</div>
<div data-line="crayon-512482090f2c4-17">17</div>
<div data-line="crayon-512482090f2c4-18">18</div>
<div data-line="crayon-512482090f2c4-19">19</div>
<div data-line="crayon-512482090f2c4-20">20</div>
<div data-line="crayon-512482090f2c4-21">21</div>
<div data-line="crayon-512482090f2c4-22">22</div>
<div data-line="crayon-512482090f2c4-23">23</div>
<div data-line="crayon-512482090f2c4-24">24</div>
</div></td>
<td>
<div>
<div>//StreamTool类如下</div>
<div>public class StreamTool {</div>
<div>        /**</div>
<div>         * 从输入流中获取数据</div>
<div>         * @param inputStream 输入流</div>
<div>         * @return 字节数组</div>
<div>         * @throws Exception</div>
<div>         */</div>
<div>        public static byte[] readInputStream(InputStream inputStream) throws Exception</div>
<div>        {</div>
<div>//实例化一个输出流</div>
<div>                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();</div>
<div>//一个1024字节的缓冲字节数组</div>
<div>                byte[] buffer = new byte[1024];</div>
<div>                int len = 0;</div>
<div>//读流的基本知识</div>
<div>                while ((len=inputStream.read(buffer)) != -1) {</div>
<div>                        outputStream.write(buffer, 0, len);</div>
<div>                }</div>
<div>//用完要关,大家都懂的</div>
<div>                inputStream.close();</div>
<div>                return outputStream.toByteArray();</div>
<div>        }</div>
<div>}</div>
</div></td>
</tr>
</tbody>
</table>
</div>
</div>
现在,我们得到了POST方法返回的String,我们输出到控制台看看是什么
<div data-settings=" minimize scroll-mouseover">
<div><textarea readonly="readonly" wrap="off" data-settings="dblclick">System.out.println(html);</textarea></div>
<div>
<table>
<tbody>
<tr>
<td data-settings="show">
<div>
<div data-line="crayon-512482090f38a-1">1</div>
</div></td>
<td>
<div>
<div>System.out.println(html);</div>
</div></td>
</tr>
</tbody>
</table>
</div>
</div>
<div align="center"></div>
没错,就是我们上文看到的HttpWatch 抓到的返回Content,也就是一段HTML代码,这说明,我们模拟浏览器POST请求成功了!
我们再试试别的搜索内容,来一个”<a href="http://www.apkbus.com/" target="_blank">Android开发</a>”(即将v_value键值对的值改成”android开发”),这时运行后,我们却从控制台得到了这样的结果:
<div align="center"></div>
经过几次试验后,发现一个规律,只要搜索内容中包括中文,就搜不到。
所以可以判定是中文编码的问题,(在开发这类客户端时候,中文编码往往是个很具困难的问题。安卓巴士开发3群的某群友提到:服务器交流用的编码 是”ISO-8859-1”,跟我起初用到的编码一致,但真实性仍需考证)所以我们修改上面的代码,将代表搜索内容的v_value对应的值编码 为”ISO-8859-1”

就将上段代码中的
<div data-settings=" minimize scroll-mouseover">
<div><textarea readonly="readonly" wrap="off" data-settings="dblclick">NameValuePair vValue = new NameValuePair("v_value" ,”android”);</textarea></div>
<div>
<table>
<tbody>
<tr>
<td data-settings="show">
<div>
<div data-line="crayon-512482090f471-1">1</div>
</div></td>
<td>
<div>
<div>NameValuePair vValue = new NameValuePair("v_value" ,”android”);</div>
</div></td>
</tr>
</tbody>
</table>
</div>
</div>
改为
<div data-settings=" minimize scroll-mouseover">
<div><textarea readonly="readonly" wrap="off" data-settings="dblclick">NameValuePair vValue = new NameValuePair("v_value" , new String(“android开发”.getBytes(),"ISO-8859-1"));</textarea></div>
<div>
<table>
<tbody>
<tr>
<td data-settings="show">
<div>
<div data-line="crayon-512482090f4ef-1">1</div>
</div></td>
<td>
<div>
<div>NameValuePair vValue = new NameValuePair("v_value" , new String(“android开发”.getBytes(),"ISO-8859-1"));</div>
</div></td>
</tr>
</tbody>
</table>
</div>
</div>
这时再运行,控制台成功输出以” android开发”为关键字的Content。

至此,我们POST请求才真正完成。 观察控制台的HTML后发现,我们需要的书目信息就在里面,只不过被一些HTML标签包裹住了,下一步我们就要解放这些信息,存储到容器里。
这里我们要用到Jsoup,一个Java开源HTML解析器(来自org.jsoup包)。
我们直接上代码,逐行解释(大家最好对应上面的HTML代码来理解)
首先我们建一个容器来装这些解析到的数据,由于我的项目是将这些数据以ListView呈现给用户,而ListView的数据是由Adapter提供,Adapter需要传一个特殊容器-包含HashMap的ArrayList(Android基础知识)
<div data-settings=" minimize scroll-mouseover">
<div><textarea readonly="readonly" wrap="off" data-settings="dblclick">//所以有
List&lt;Map&lt;String,Object&gt;&gt; list = new ArrayList&lt;Map&lt;String,Object&gt;&gt;();
//开始使用Jsoup
//Jsoup支援一个Document类 将刚才的html转化成Document
Document document = Jsoup.parse(html);
//一个Document又由elements组成 我们选择”tr”开头的标签,存入 trs元素群中
Elements trs = document.select("tr");
//得到整个HTML中包含tr的标签的个数
int totalTrs = trs.size();
//我们可以观察上面没有搜索结果的那个HTML。发现,如果totalTrs&lt;=3就表示没结果。
//只要有书目结果totalTrs必定大于3,于是
if(totalTrs &gt; 3)
for(int i = 0;i &lt; totalTrs - 3;i++)
{
//观察HTML,从第i+2个tr开始,包含的才是我们要的书目信息
//我们从每个tr中选出td标签元素群
Elements tds = trs.get(i + 2).select("td");
//得到每个tr中td的个数
int totalTds = tds.size();
//一个临时的HashMap,里面是String-Object键值对
Map&lt;String,Object&gt; map = new HashMap&lt;String,Object&gt;();
//j是一个标识数
for(int j =0;j &lt; totalTds ;j++)
{
switch (j) {
//0表示第一个,即书名
//put方法即向map加入一条键值对
//html()方法就得到标签括起来的内容
case 0:
map.put("book_title", tds.get(j).html().toString());
break;
case 1:
//1表示第二个,即作者
map.put("book_author", tds.get(j).html().toString());
break;
case 2:
//2表示第三个,即出版信息
map.put("book_press", tds.get(j).html().toString());
break;
case 3:
//3表示第四个,即页数
map.put("book_page", tds.get(j).html().toString());
break;
case 4:
//4表示第五个,即价格
map.put("book_price", tds.get(j).html().toString());
break;
case 5:
//5表示第六个,即索取号
map.put("book_noFor", tds.get(j).html().toString());
break;
case 6:
//6表示第七个,即那段网址
//那段网址td中又包含一个a标签,a标签的href属性的值就是网址
//attr(“href”)可以返回href属性的值
map.put("book_detail", tds.get(j).select("a").attr("href").toString());
break;
default:
break;
}
}
list.add(map);
}</textarea></div>
<div>
<table>
<tbody>
<tr>
<td data-settings="show">
<div>
<div data-line="crayon-512482090f569-1">1</div>
<div data-line="crayon-512482090f569-2">2</div>
<div data-line="crayon-512482090f569-3">3</div>
<div data-line="crayon-512482090f569-4">4</div>
<div data-line="crayon-512482090f569-5">5</div>
<div data-line="crayon-512482090f569-6">6</div>
<div data-line="crayon-512482090f569-7">7</div>
<div data-line="crayon-512482090f569-8">8</div>
<div data-line="crayon-512482090f569-9">9</div>
<div data-line="crayon-512482090f569-10">10</div>
<div data-line="crayon-512482090f569-11">11</div>
<div data-line="crayon-512482090f569-12">12</div>
<div data-line="crayon-512482090f569-13">13</div>
<div data-line="crayon-512482090f569-14">14</div>
<div data-line="crayon-512482090f569-15">15</div>
<div data-line="crayon-512482090f569-16">16</div>
<div data-line="crayon-512482090f569-17">17</div>
<div data-line="crayon-512482090f569-18">18</div>
<div data-line="crayon-512482090f569-19">19</div>
<div data-line="crayon-512482090f569-20">20</div>
<div data-line="crayon-512482090f569-21">21</div>
<div data-line="crayon-512482090f569-22">22</div>
<div data-line="crayon-512482090f569-23">23</div>
<div data-line="crayon-512482090f569-24">24</div>
<div data-line="crayon-512482090f569-25">25</div>
<div data-line="crayon-512482090f569-26">26</div>
<div data-line="crayon-512482090f569-27">27</div>
<div data-line="crayon-512482090f569-28">28</div>
<div data-line="crayon-512482090f569-29">29</div>
<div data-line="crayon-512482090f569-30">30</div>
<div data-line="crayon-512482090f569-31">31</div>
<div data-line="crayon-512482090f569-32">32</div>
<div data-line="crayon-512482090f569-33">33</div>
<div data-line="crayon-512482090f569-34">34</div>
<div data-line="crayon-512482090f569-35">35</div>
<div data-line="crayon-512482090f569-36">36</div>
<div data-line="crayon-512482090f569-37">37</div>
<div data-line="crayon-512482090f569-38">38</div>
<div data-line="crayon-512482090f569-39">39</div>
<div data-line="crayon-512482090f569-40">40</div>
<div data-line="crayon-512482090f569-41">41</div>
<div data-line="crayon-512482090f569-42">42</div>
<div data-line="crayon-512482090f569-43">43</div>
<div data-line="crayon-512482090f569-44">44</div>
<div data-line="crayon-512482090f569-45">45</div>
<div data-line="crayon-512482090f569-46">46</div>
<div data-line="crayon-512482090f569-47">47</div>
<div data-line="crayon-512482090f569-48">48</div>
<div data-line="crayon-512482090f569-49">49</div>
<div data-line="crayon-512482090f569-50">50</div>
<div data-line="crayon-512482090f569-51">51</div>
<div data-line="crayon-512482090f569-52">52</div>
<div data-line="crayon-512482090f569-53">53</div>
<div data-line="crayon-512482090f569-54">54</div>
<div data-line="crayon-512482090f569-55">55</div>
<div data-line="crayon-512482090f569-56">56</div>
<div data-line="crayon-512482090f569-57">57</div>
<div data-line="crayon-512482090f569-58">58</div>
<div data-line="crayon-512482090f569-59">59</div>
<div data-line="crayon-512482090f569-60">60</div>
<div data-line="crayon-512482090f569-61">61</div>
<div data-line="crayon-512482090f569-62">62</div>
<div data-line="crayon-512482090f569-63">63</div>
</div></td>
<td>
<div>
<div>//所以有</div>
<div>List&lt;Map&lt;String,Object&gt;&gt; list = new ArrayList&lt;Map&lt;String,Object&gt;&gt;();</div>
<div>//开始使用Jsoup</div>
<div>//Jsoup支援一个Document类   将刚才的html转化成Document</div>
<div>Document document = Jsoup.parse(html);</div>
<div>//一个Document又由elements组成  我们选择”tr”开头的标签,存入 trs元素群中</div>
<div>Elements trs = document.select("tr");</div>
<div>//得到整个HTML中包含tr的标签的个数</div>
<div>int totalTrs = trs.size();</div>
<div>//我们可以观察上面没有搜索结果的那个HTML。发现,如果totalTrs&lt;=3就表示没结果。</div>
<div>//只要有书目结果totalTrs必定大于3,于是</div>
<div>if(totalTrs &gt; 3)</div>
<div>for(int i = 0;i &lt; totalTrs - 3;i++)</div>
<div>{</div>
<div>//观察HTML,从第i+2个tr开始,包含的才是我们要的书目信息</div>
<div>//我们从每个tr中选出td标签元素群</div>
<div>                        Elements tds = trs.get(i + 2).select("td");</div>
<div>//得到每个tr中td的个数</div>
<div>                        int totalTds = tds.size();</div>
<div>//一个临时的HashMap,里面是String-Object键值对</div>
<div>                        Map&lt;String,Object&gt; map = new HashMap&lt;String,Object&gt;();</div>
<div>//j是一个标识数</div>
<div>                        for(int j =0;j &lt; totalTds ;j++)</div>
<div>                        {</div>
<div>                                switch (j) {</div>
<div>//0表示第一个,即书名</div>
<div>//put方法即向map加入一条键值对</div>
<div>//html()方法就得到标签括起来的内容</div>
<div>                                case 0:</div>
<div>                                        map.put("book_title", tds.get(j).html().toString());</div>
<div>                                        break;</div>
<div>                                case 1:</div>
<div>//1表示第二个,即作者</div>
<div>                                        map.put("book_author", tds.get(j).html().toString());</div>
<div>                                        break;</div>
<div>                                case 2:</div>
<div>//2表示第三个,即出版信息</div>
<div>                                        map.put("book_press", tds.get(j).html().toString());</div>
<div>                                        break;</div>
<div>                                case 3:</div>
<div>//3表示第四个,即页数</div>
<div>                                        map.put("book_page", tds.get(j).html().toString());</div>
<div>                                        break;</div>
<div>                                case 4:</div>
<div>//4表示第五个,即价格</div>
<div>                                        map.put("book_price", tds.get(j).html().toString());</div>
<div>                                        break;</div>
<div>                                case 5:</div>
<div>//5表示第六个,即索取号</div>
<div>                                        map.put("book_noFor", tds.get(j).html().toString());</div>
<div>                                        break;</div>
<div>                                case 6:</div>
<div>//6表示第七个,即那段网址</div>
<div>//那段网址td中又包含一个a标签,a标签的href属性的值就是网址</div>
<div>//attr(“href”)可以返回href属性的值</div>
<div>                                        map.put("book_detail", tds.get(j).select("a").attr("href").toString());</div>
<div>                                        break;</div>
<div>                                default:</div>
<div>                                        break;</div>
<div>                                }</div>
<div>                        }</div>
<div>                        list.add(map);</div>
<div>}</div>
</div></td>
</tr>
</tbody>
</table>
</div>
</div>
list就是我们需要的ArrayList啦

上面所有代码调通后,我们只需一些简单的复制粘贴,就可以放在我们的Android工程中,加上一段简单的代码就可以让ListView显示这个ArrayList。(由于没有任何技术含量,以及该项目暂未上线,此段代码不予以展示,敬请谅解)

接下来,我们一个页面最多只包含10个书目信息,而我们校图书馆,光以”Java”为关键字的书就超过1000本,怎么来显示完全呢,一次显示所有 的书肯定不现实。首先数据量太大,手机无法承受;消耗流量过大,用户体验极差。所以,我们就需要ListView能够动态加载数据,即一开始显示十项,如 果用户此时拉动ListView显示完十项之后,自动联网,再加载十项(如果还有十项的话),这样的用户体验会非常顺畅。
这个功能的核心是,我们的ListView需要实现OnScrollListener接口。
如果你的ListView所在的Activity继承的是ListActivity的话,只需在extends ListActivity后面加上implements OnScrollListener,这时你需要复写onScroll和onScrollStateChanged。如果你的ListView是从 XMLgetView 得到的,你只需为它setOnScrollListener,也会需要你复写onScroll和onScrollStateChanged。

不管你用哪种方法,我们只用修改onScroll方法
<div data-settings=" minimize scroll-mouseover">
<div><textarea readonly="readonly" wrap="off" data-settings="dblclick">@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
//关键的判断代码,这句话表示用户将ListView拉至最底部
if(firstVisibleItem + visibleItemCount == totalItemCount)
//你只需要把继续得到下面十项的代码写在这里,就可以实现上述功能了。
//同样再使用一次POST方法,不再赘述
//代码由于同样原因不予以展示,敬请谅解</textarea></div>
<div>
<table>
<tbody>
<tr>
<td data-settings="show">
<div>
<div data-line="crayon-512482090f5ee-1">1</div>
<div data-line="crayon-512482090f5ee-2">2</div>
<div data-line="crayon-512482090f5ee-3">3</div>
<div data-line="crayon-512482090f5ee-4">4</div>
<div data-line="crayon-512482090f5ee-5">5</div>
<div data-line="crayon-512482090f5ee-6">6</div>
<div data-line="crayon-512482090f5ee-7">7</div>
<div data-line="crayon-512482090f5ee-8">8</div>
<div data-line="crayon-512482090f5ee-9">9</div>
</div></td>
<td>
<div>
<div>@Override</div>
<div>        public void onScroll(AbsListView view, int firstVisibleItem,</div>
<div>                        int visibleItemCount, int totalItemCount) {</div>
<div>                // TODO Auto-generated method stub</div>
<div>//关键的判断代码,这句话表示用户将ListView拉至最底部</div>
<div>                if(firstVisibleItem + visibleItemCount == totalItemCount)</div>
<div>//你只需要把继续得到下面十项的代码写在这里,就可以实现上述功能了。</div>
<div>//同样再使用一次POST方法,不再赘述</div>
<div>//代码由于同样原因不予以展示,敬请谅解</div>
</div></td>
</tr>
</tbody>
</table>
</div>
</div>
至此,文章开头的几个知识点已经全部讲解完毕,时间仓促,事物繁忙,可能会影响文章质量,还请大家多多包涵。 如果有问题,可以直接回帖、发论坛信息或通过Email:anliupeinye@gmail.com联系我。

项目成品展示:
<div align="center"></div>
最后感谢安卓巴士论坛、安卓王子、安卓巴士开发3群的群友的支持。
转自<a href="http://www.apkbus.com/android-17712-1-1.html">http://www.apkbus.com/android-17712-1-1.html</a>
<div>Author:snow | Categories:<a title="查看 android-java 中的全部文章" href="http://www.j2men.com/index.php/archives/category/all/code_and_resource" rel="category tag">android-java</a>、<a title="查看 全部文章 中的全部文章" href="http://www.j2men.com/index.php/archives/category/all" rel="category tag">全部文章</a> | Tags: <a href="http://www.j2men.com/index.php/archives/tag/httpclient%e6%a8%a1%e6%8b%9fpost%e8%af%b7%e6%b1%82" rel="tag">HttpClient模拟POST请求</a>、<a href="http://www.j2men.com/index.php/archives/tag/httpwatch%e6%8a%93%e5%8c%85" rel="tag">HttpWatch抓包</a>、<a href="http://www.j2men.com/index.php/archives/tag/j2men" rel="tag">J2MEN</a>、<a href="http://www.j2men.com/index.php/archives/tag/jsoup%e8%a7%a3%e6%9e%90html%e4%bb%a3%e7%a0%81" rel="tag">Jsoup解析HTML代码</a>、<a href="http://www.j2men.com/index.php/archives/tag/%e4%b8%80%e6%ad%a5%e6%ad%a5%e6%95%99%e4%bd%a0%e4%b8%ba%e7%bd%91%e7%ab%99%e5%bc%80%e5%8f%91android%e5%ae%a2%e6%88%b7%e7%ab%af" rel="tag">一步步教你为网站开发Android客户端</a>、<a href="http://www.j2men.com/index.php/archives/tag/%e5%8a%a8%e6%80%81%e6%9b%b4%e6%96%b0listview" rel="tag">动态更新ListView</a>、<a href="http://www.j2men.com/index.php/archives/tag/%e5%8f%8b%e7%9b%9f-%e5%ae%89%e5%8d%93%e5%b7%b4%e5%a3%abandroid%e5%bc%80%e5%8f%91%e5%8e%9f%e5%88%9b%e6%95%99%e7%a8%8b%e5%a4%a7%e8%b5%9b" rel="tag">友盟—安卓巴士Android开发原创教程大赛</a>、<a href="http://www.j2men.com/index.php/archives/tag/%e5%ae%89%e5%8d%93%e5%b7%b4%e5%a3%ab" rel="tag">安卓巴士</a>、<a href="http://www.j2men.com/index.php/archives/tag/%e5%b0%8f%e5%ba%94%e7%94%a8%e5%8d%8f%e4%bc%9a" rel="tag">小应用协会</a></div>

posted @ 2013-06-30 01:05  山顶的鱼  阅读(611)  评论(0编辑  收藏  举报