上一篇文章《Android也架构之三:简单工厂模式优化网络请求》中,我们知道了如何通过简单工厂模式去获取网络的内容,又知道了如何把这些内容显示在我们的界面上,但是我们拿到的都是html文本内容。这篇文章中,我们将讲到了如何去解析这些html,获得我们想要的内容。
通过这篇文章的学习,你将学会一下几个知识点:
1,门面模式在android中的应用
2,学会使用jsoup框架解析html。
废话少说,我们首先来看下什么是门面模式:
门面模式要求一个子系统的外部与其内部的通信必须通过一个统一的门面(Facade)对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。
门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
子系统(subsystem)角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
在我们一下的例子中,门面是facade.java,子系统有网络系统(从网络中获取响应数据)和数据解析系统(解析html代码)
网络系统的代码可以直接看上一篇文章《Android也架构之三:简单工厂模式优化网络请求》的代码,这里就不在贴出。
首先我们来看一下html数据解析代码:
package com.devchina.analyze;
import java.util.ArrayList;
import java.util.List;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
* @title HTML解析类
* @description 描述
* @company 探索者网络工作室(www.tsz.net)
* @author michael Young (www.YangFuhai.com)
* @version 1.0
* @created 2012-9-10
*/
public class HtmlAnalyze implements DataAnalyze {
@Override
public List<String> getTitleList(String strData) {
List<String> strList = new ArrayList<String>();
Document doc = Jsoup.parse(strData,"utf-8");//获得document
Element content = doc.body();//获得body
Elements links = content.getElementsByTag("a");//获得所有的超级链接
for (Element link : links) { //遍历所有的超级链接
String linkHref = link.attr("href");
String linkText = link.text();
System.out.println("---------linkHref:"+linkHref);
System.out.println("---------linkText:"+linkText);
if(linkHref.startsWith("forum.php?mod=viewthread")) //如果是文章的超级链接的话,添加到list 返回
strList.add(linkText);
}
return strList;
}
}
数据解析接口和数据解析工厂类(为什么用工厂,可以查看上一篇文章)
DataAnalyze.java
package com.devchina.analyze;
import java.util.List;
/**
* @title 数据解析接口
* @description 解析数据
* @company 探索者网络工作室(www.tsz.net)
* @author michael Young (www.YangFuhai.com)
* @version 1.0
* @created 2012-9-10
*/
public interface DataAnalyze {
public List<String> getTitleList(String strData);
}
DataAnalyzeFactory.java
package com.devchina.analyze;
/**
* @title 数据解析工厂类
* @description 描述
* @company 探索者网络工作室(www.tsz.net)
* @author michael Young (www.YangFuhai.com)
* @version 1.0
* @created 2012-9-10
*/
public class DataAnalyzeFactory {
public static DataAnalyze getAnalyze(){
//这里很简单,直接放回了html解析类,以后可以通过扩展实现xml解析,json解析等功能
return new HtmlAnalyze();
}
}
接下来我们来看下门面模式的核心类facade.java
package com.devchina.facade;
import java.util.List;
import com.devchina.analyze.DataAnalyzeFactory;
import com.devchina.http.HttpFactory;
/**
* @title 获取devchina.com的文章列表门面
* @description 描述
* @company 探索者网络工作室(www.tsz.net)
* @author michael Young (www.YangFuhai.com)
* @version 1.0
* @created 2012-9-10
*/
public class Facade {
//门面中获取devchina.com的文章列表的方法
public static List<String> getTitleListFromDevChina(){
//首选是通过网络模块去获取www.devchina.com的html内容
String strHtml = HttpFactory.getHttp().getUrlContext("http://www.devchina.com/forum.php?mod=forumdisplay&fid=63");
//通过解析模块获取去解析获得到的内容(解析工厂中目前只有html解析,以后根据项目扩展可以添加xml解析,json解析等)
return strHtml != null ? DataAnalyzeFactory.getAnalyze().getTitleList(strHtml) : null;
}
}
这里我多唠叨几句,
门面模式要求一个子系统(这里的就是网络子系统,数据解析子系统)的外部与其内部的通信必须通过一个统一的门面(Facade)对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。
在这里,我们明显的能感觉到,当客户端FacadeActivity要去实现某项功能的时候,无需与各个子系统去打交道,直接去门面获取就行了,这样就降低了耦合度,当将来由于某些原因,子系统改变了,我们的客户端的代码也无需改变,同时子系统又采用了工厂模式,基于接口编程原则(可插拔),又给系统降低了一层的耦合。
FacadeActivity.java 这个是android用来显示数据的activity组件
package com.devchina.ui;
import java.util.List;
import com.devchina.facade.Facade;
import com.devchina.facade.R;
import com.devchina.facade.R.id;
import com.devchina.facade.R.layout;
import com.devchina.http.HttpFactory;
import com.devchina.http.HttpUtils;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
/**
* @title 客户端的acitivity
* @description (门面模式)
* @company 探索者网络工作室(www.tsz.net)
* @author michael Young (www.YangFuhai.com)
* @version 1.0
* @created 2012-8-19
*/
public class FacadeActivity extends Activity {
TextView mTv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTv = (TextView) findViewById(R.id.textView);
mTv.setText("正在加载www.devchina.com数据。。。");
new Thread(new Runnable() {
@Override
public void run() {
//通过门面 直接去获取www.devchina.com的文章列表,不用去和网络模块,解析模块等模块打交道,只管去门面获取就行了
//就像我们去买东西的时候,超市(facade)里面已经有了很多东西了,我们无需去和各个厂家打交道,我们直接去超市获取,无需知道超市是怎么去和厂家沟通交流的
List<String> strList = Facade.getTitleListFromDevChina();
if(strList!=null && strList.size() >0){
String strContext = "";
for(String str : strList)
strContext += str;
final String showText = strContext;
System.out.println("-------strContext:" + strContext);
runOnUiThread(new Runnable() {
public void run() {
if (showText != null)
mTv.setText(showText);
else
mTv.setText("加载失败。。。");
}
});
}
}
}).start();
}
}
现在代码已经完毕。无图无真相,上图。
代码下载地址:
http://download.youkuaiyun.com/detail/michael_yy/4561839
文章出处说明来之优快云:http://blog.youkuaiyun.com/michael_yy/article/details/7965168
大家多多指教,转载请注明来之 http://www.devchina.com/ 或者http://blog.youkuaiyun.com/michael_yy, 谢谢。
谢谢大家关注,我继续在博客中讲解了经典的23中模式中在android实际项目中灵活运用,下一篇 《Android也架构之五:适配器模式把html文章列表显示在android的listview上》敬请关注。