导入HttpClient的4个包commons-codec、commons-httpclient、commons-logging、log4j。
//实例化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" , "查 询")); 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();
//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(); } }
现在,我们得到了POST方法返回的String,我们输出到控制台看看是什么
System.out.println(html);
NameValuePair vValue = new NameValuePair("v_value" ,”android”);
改为
NameValuePair vValue = new NameValuePair("v_value" , new String(“android开发”.getBytes(),"ISO-8859-1"));
这时再运行,控制台成功输出以” android开发”为关键字的Content。
至此,我们POST请求才真正完成。 观察控制台的HTML后发现,我们需要的书目信息就在里面,只不过被一些HTML标签包裹住了,下一步我们就要解放这些信息,存储到容器里。
这里我们要用到Jsoup,一个Java开源HTML解析器(来自org.jsoup包)。
我们直接上代码,逐行解释(大家最好对应上面的HTML代码来理解)
首先我们建一个容器来装这些解析到的数据,由于我的项目是将这些数据以ListView呈现给用户,而ListView的数据是由Adapter提供,Adapter需要传一个特殊容器-包含HashMap的ArrayList(Android基础知识)
//所以有 List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); //开始使用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<=3就表示没结果。 //只要有书目结果totalTrs必定大于3,于是 if(totalTrs > 3) for(int i = 0;i < 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<String,Object> map = new HashMap<String,Object>(); //j是一个标识数 for(int j =0;j < 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); }
ist就是我们需要的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方法
@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub //关键的判断代码,这句话表示用户将ListView拉至最底部 if(firstVisibleItem + visibleItemCount == totalItemCount) //你只需要把继续得到下面十项的代码写在这里,就可以实现上述功能了。 //同样再使用一次POST方法,不再赘述 //代码由于同样原因不予以展示,敬请谅解
至此,文章开头的几个知识点已经全部讲解完毕,时间仓促,事物繁忙,可能会影响文章质量,还请大家多多包涵。 如果有问题,可以直接回帖、发论坛信息或通过Email:[email protected]联系我。
项目成品展示:
转自:http://www.apkbus.com/android-17712-1-1.html