rss 를 읽어서 보여주는 프로그램을 작성중이다. 그래서 구글링을 좀 해보니, rss feed reader 를 쉽게 만드는 법이라는 질문의 글(ref. 1) 을 찾을 수 있었다.
여기서 추천하는 문서가 ref.2 이다.
XML 관련 android API
android SDK에서는 XML 관련 API 로- Simple API for XML(SAX)
- DOM
이중에 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
StackRssItem.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 의 모습이다.
댓글 없음:
댓글 쓰기