[컴][안드로이드] 간단한 rss feed parser

rss feed parser, rss feed reader 만들기

rss 를 읽어서 보여주는 프로그램을 작성중이다. 그래서 구글링을 좀 해보니, rss feed reader 를 쉽게 만드는 법이라는 질문의 글(ref. 1) 을 찾을 수 있었다.
여기서 추천하는 문서가 ref.2 이다.

XML 관련 android API

android SDK에서는 XML 관련 API 로
  • Simple API for XML(SAX)
  • DOM
을 제공한다.[ref.2]

이중에 SAX가 메모리를 적게 사용하고, 빠른 parser 라고 한다. 그리고 요새 Java 쪽에 Streaming API for XML 가 있는데 이 Java의 StAX API 대신에 android 에선 XML pull parser 를 제공한다. 고 한다.[ref.2]

ref. 2 에서 제공하는 소스코드가 개인적인 취향과 맞지 않아 취향에 맞게 조금 수정하였다. 그리고 실행해 볼 수 있는 MainActivity 도 추가했다.
Download source
시간이 나면 차후에 소스에 대해 자세히 얘기하도록 하자.


package com.muchart;



import java.util.ArrayList;

import java.util.List;


import com.namh.util.AndroidSaxFeedParser;
import com.namh.util.RssItem;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


import android.widget.BaseAdapter;
import android.widget.TextView;


//--------------------------------------------------------
public class MainActivity extends ListActivity {

 private CustomAdapter mAdapter;

 
 //--------------------------------------------------------
 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        List<RssItem> messages = loadFeed();
        

        mAdapter = new CustomAdapter();
        for (int i = 0; i < 50; i++) {
            mAdapter.addItem(messages.get(i).getTitle());
            if (i % 4 == 0) {
                //mAdapter.addSeparatorItem("separator " + i);
            }
        }
        setListAdapter(mAdapter);
    }
 
 
 //--------------------------------------------------------
 private class CustomAdapter extends BaseAdapter{
  
  /**
   * layout inflator
   * 
   * Instantiates a layout XML file into its corresponding View objects.
   * @ref : http://developer.android.com/reference/android/view/LayoutInflater.html
   */
  private LayoutInflater mInflater;
  private ArrayList<String> mData = new ArrayList<String>();

  
  //--------------------------------------------------------
  public CustomAdapter() {
   mInflater = (LayoutInflater)getSystemService(
     Context.LAYOUT_INFLATER_SERVICE);
  }

  
  //--------------------------------------------------------
  public void addSeparatorItem(String string) {
   // TODO Auto-generated method stub
   
  }
  
  //--------------------------------------------------------
  public void addItem(String string) {
   mData.add(string);
   notifyDataSetChanged();
  }
  
  
  //--------------------------------------------------------
  @Override
  public int getCount() {
   return mData.size();
  }


  //--------------------------------------------------------
  @Override
  public Object getItem(int position) {
   return mData.get(position);
  }


  //--------------------------------------------------------
  @Override
  public long getItemId(int position) {
   return position;
  }


  //--------------------------------------------------------
  @Override
  public View getView(int pos, View convertView, ViewGroup parent) {
   TextView textView = null;
   
   if(convertView == null){
    convertView = mInflater.inflate(R.layout.item1, null);
    textView = (TextView)convertView.findViewById(R.id.text);
    convertView.setTag(textView);
   }
   else
   {
    textView = (TextView)convertView.getTag();
   }
   
   textView.setText(mData.get(pos));
   
   return convertView;
  }

  
 }
 
 //--------------------------------------------------------
 private List<RssItem> loadFeed(){
  List<RssItem> messages = null;
     try{
      Log.i("AndroidNews", "ParserType AndroidSAX");
      String feedUrl = "http://www.billboard.com/rss/charts/hot-100";

      long start = System.currentTimeMillis();
      
      AndroidSaxFeedParser saxParser = null;
      // retrieve the rss feed and parse it.
      new Thread(saxParser = new AndroidSaxFeedParser(feedUrl)).start();
      // get the parsed data
      while(messages == null){
       Thread.sleep(1000);
       messages = saxParser.getMessages();
      }
      long duration = System.currentTimeMillis() - start;
      
      Log.i("AndroidNews", "Parser duration=" + duration);

      
     } catch (Throwable t){
      Log.e("AndroidNews",t.getMessage(),t);
     }
     return messages;
    }
 

 
}


Android SAX Parser

Stack
RssItem.setDate(String) line: 49
AndroidSaxFeedParser$4.end(String) line: 88    
RootElement$Handler.endElement(String, String, String) line: 197    
ExpatParser.endElement(String, String, String) line: 156    
ExpatParser.appendBytes(int, byte[], int, int) line: not available [native method]    
ExpatParser.parseFragment(InputStream) line: 513    
ExpatParser.parseDocument(InputStream) line: 474    
ExpatReader.parse(InputStream, String, String, String) line: 321    
ExpatReader.parse(InputSource) line: 279    
Xml.parse(InputStream, Xml$Encoding, ContentHandler) line: 84

SaxParser
RootElement root = new RootElement(RSS);
Element channel = root.getChild(CHANNEL);
Element item = channel.getChild(ITEM);
item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener(){
    public void end(String body) {
        currentItem.setDate(body);
    }
});
...
Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());

위의 Stack 은 SaxParser 에서 override 한 end() 가 불려지는 stack 의 모습이다.


References

  1. http://stackoverflow.com/questions/2428682/easiest-way-to-implement-rss-reader-on-google-android
  2. http://www.ibm.com/developerworks/opensource/library/x-android/index.html
  3. http://developer.samsung.com/android/technical-docs/Parsing-XML-in-Android

댓글 없음:

댓글 쓰기