Monday, August 16, 2010

我的隨手新聞RSS解析

話說︰
  小鰻最近在忙一個專案,其中有一段剛好跟RSS有關,研究了3、4天的SDK範例大全和另一本開發實務的書,在這裡稍微把概念記錄下來。
  android有提供幾種方式去抓取RSS資料來源,最為人知的就是使用SAXParser分析器了。
  RSS說簡單了,也只不過是一個xml檔(也有可能是其他的副檔名)。它有一定的規範與格式,所以在解析各大新聞臺的RSS時,也變得有跡可尋。

  以下是常看到的RSSxml檔案格式
  
<itme>
    <title>新聞的標題</title>
    <link>新聞的連結網址</link>
    <description>新聞內容簡述</description>
    <pubDate>發佈新聞的時間</pubDate>
</item>
  所以啦,所謂的RSS解析器,說白一點,就是在這些標籤裡,把字取出來啦!
  通常各大網站都會提供RSS新聞的連結,像yam新聞的RSS網址是這樣子的︰
http://c.yam.com/news/o5link/r.c?http://n.yam.com/RSS/Rss_life.xml
所以,到時候程式裡一定要有個地方能夠存這個網址。
------------------------------------------------------

RSS解析器裡會有4個工人分工合作著
(1)XMLReader - 閱讀工人
(2)MyAdapter(繼承自BaseAdapter) - 版面配置工人
(3)MyHandler(繼承自DefaultHandler) - 文字分配工人
(4)一個具物件導向特性的類別News - 模版工人

要能夠解析一份RSS,Android交給了4個工人幫忙
(1)XMLReader
第1個工人既然叫閱讀工人,我們就來看看這個工人是怎麼讀書的吧︰
path = "http://c.yam.com/news/o5link/r.c?http://n.yam.com/RSS/Rss_life.xml";
URL url = null;

try{
    url = new URL(path);//呼叫網址進來
    SAXParserFactory spf = SAXParserFactory.newInstance();//先蓋一個工廠
    SAXParser sp = spf.newSAXParser();//工廠有一個知識不太高的解析工人
    XMLReader xr = sp.getXMLReader();//也有一個閱讀工人
    MyHandler myHandler = new MyHandler();//用到了我們之後建立的分配工人
    xr.setContentHandler(myHandler);//將閱讀工人和分配工人做結合
    xr.parse(new InputSource(url.openStream()));//閱讀工人用parse去開啟一個InputStream放資料
    
    data = myHandler.getParsedData();//getParsedData()方法會在myHandler裡看到
}catch(Exception e){
    log.i("message","wrong!");
    }
原來光一個閱讀工人,就已經做了一些的前置動作了。

(2)MyAdapter
其實這個版面配置工人還真的是可有可無,要不是主編要求取出來的"新聞發佈時間"不能和"新聞標題"一樣大,還真的是不用請版面配置工人出來,用原本的android預設配置就好
這個配置工人,android希望我們繼承自BaseAdapter,而且,還規範了我們必須實作以下4個method
//建構子
public MyAdapter(Context context,List lt){
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount(){
    return 數量;
    }
@Override
public int getItem(int position){
    return position;
    }
@Override
public int getItemId(){
    return position;
    }
@Override
public View getView(int position,View convertView,ViewGroup par){
    ViewHolder holder;
    if(convertView == null){
    convertView = mInflater.inflate(R.layout.news_row, null);
    holder = new ViewHolder();
    holder.text = (TextView) convertView.findViewById(R.id.text);
    convertView.setTag(holder);
    }else{
    holder = (ViewHolder) convertView.getTag();
    }
    return convertView;
  }

class ViewHolder{//為自己訂的版面的xml做一個類別
    TextView text;
    }
}
最後面這段「為自己訂的版面的xml做一個類別」是什麼意思呢?
其實配置工人通常會帶一個小老婆出現︰
news_row.xml
他們其實是很親密的,正所謂孟不離焦啊!
一個負責外表(xml),另一個是對應的骨架(class ViewHolder)

(3)MyHandler
既然叫Handler,當然什麼事都要幫你搞定囉!
它也有幾個一定要我們覆寫的method
public class MyHandler extends DefaultHandler{
    private List<News> li;

    public List getParsedData(){//這個是我們自己寫的,沒有一定要覆寫
    return li;
    }
    
    @Override
    pubilc void starDocument() throws SAXExcption{
    li = new ArrayList<News>();//在程式解析之初,先建立一個ArrayList容器
    }

    @Override
    pubilc void endDocument() throws SAXExcption{
    }

    @Override
    pubilc void starElement(String namespaceURI, String localName, String qName, Attributes atts) thtows SAXException{
    news = new News();//在程式解析之初,先產生實體
    }

    @Override
    pubilc void endElement(String namespaceURI, String localName, String qName, Attributes atts) thtows SAXException{
    //更多程式碼
    }

    @Override  //取標籤內的字的方式
    pubilc void characters(char ch[], int start, int length){
    //更多程式碼    
    }
}
這段的程式跑法是︰
starElement()→characters()→endElement()→starElement()→characters()→endElement().....
將一個一個的標籤辨識出來並跑完



(4)News類別
既然叫模版工人,就是說從解析器解出來的字串,要有一個一個的對應去接收資料,好讓容器能歸納整理咩

所以,模版的程式碼超基本
public class News{
    private String title="";  //新聞的標題存在這裡
    private String link="";  //新聞的連結網址存在這裡
    private String desc="";  //新聞的大綱描述存在這裡
    private String date="";  //新聞的發佈時間存在這裡
//以下是一堆的getter和setter
//像︰
    public String getTitle(){
    return title;
    }
    public String setTitle(String title){
    this.title = title;
    }
    //更多程式碼    
}

最後最後,有一個超關鍵,如果你忽略了,可能都不知道為什麼會無法解析或上網咧!

請你在AndroidManifest.xml這個apk基本配面版中的<application>區塊外,做以下的新增
<uses-permission android:name="android.permission.INTERNET" />
因為android預設的apk連網功能是關閉的,必須透過上述的設定將上網權限打開。

好啦!大功告成。
程式不多不少,但是就是因為大家的配合,才產生出了好用的RSS隨手新聞。

下臺一鞠躬(笑)。

No comments: