最近开始学习android,使用的资料是IBM developerWorks的android开发的文章,个人觉得对android学习有很大的参考价值。在ibm中国上有中文版,但不知道是否翻译上的疏漏,还是由于android1.5版本以后的差异,文章中的代码在调试时总是有这样那样的问题(哪怕是一步一步照着文章做)。所以自己对其中的内容进行了一些整理,使后来者少走弯路。

一、构建Android 手机 RSS 阅读器

1、在eclipse中新建andriod project,工程名:rss,sdk:android1.6,activity:main。

2、打开droid draw,设计一个界面,generate xml代码如下:

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayout

android:id="@+id/widget28"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical"

xmlns:android="http://schemas.android.com/apk/res/android"

>

<TextView

android:id="@+id/feedtitle"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Android RSSReader"

>

</TextView>

<TextView

android:id="@+id/feedpubdate"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

>

</TextView>

<ListView

android:id="@+id/itemlist"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

>

</ListView>

</LinearLayout>

将xml代码复制粘贴到main.xml中(原来的内容删除)。

3、新建类RSSItem,这是个pojo类,映射了rss中的item元素:

publicclassRSSItem {

privateString_title=null;

privateString_description=null;

privateString_link=null;

privateString_category=null;

privateString_pubdate=null;

RSSItem()

{

}

voidsetTitle(String title)

{

_title= title;

}

voidsetDescription(String description)

{

_description= description;

}

voidsetLink(String link)

{

_link= link;

}

voidsetCategory(String category)

{

_category= category;

}

voidsetPubDate(String pubdate)

{

_pubdate= pubdate;

}

String getTitle()

{

return_title;

}

String getDescription()

{

return_description;

}

String getLink()

{

return_link;

}

String getCategory()

{

return_category;

}

String getPubDate()

{

return_pubdate;

}

publicString toString()

{

// limit how much text you display

if(_title.length() > 42)

{

return_title.substring(0, 42) +"...";

}

return_title;

}

}

4、新建pojo类RSSFeed,映射rss中的channel元素:

publicclassRSSFeed

{

privateString_title=null;

privateString_pubdate=null;

privateint_itemcount= 0;

privateList<RSSItem>_itemlist;

RSSFeed()

{

_itemlist=newVector<RSSItem>(0);

}

intaddItem(RSSItem item)

{

_itemlist.add(item);

_itemcount++;

return_itemcount;

}

RSSItem getItem(intlocation)

{

return_itemlist.get(location);

}

List<RSSItem> getAllItems()

{

return_itemlist;

}

intgetItemCount()

{

return_itemcount;

}

voidsetTitle(String title)

{

_title= title;

}

voidsetPubDate(String pubdate)

{

_pubdate= pubdate;

}

String getTitle()

{

return_title;

}

String getPubDate()

{

return_pubdate;

}

}

5、新建helper类RSSHandler,用于对rss进行xml解析,并将解析结果包装为RSSFeed和RSSItem对象,方便在ui界面中显示:

publicclassRSSHandlerextendsDefaultHandler{//继承DefaultHandler,方便进行sax解析

RSSFeed_feed;//临时变量,用于保存解析过程中的channel

RSSItem_item;//临时变量,用于保存解析过程中的item

//标记变量,用于标记在解析过程中我们关心的几个标签

intcurrentstate= 0;//若不是我们关心的标签,记做0

finalintRSS_TITLE= 1;//若是title标签,记做1,注意有两个title,但我们都保存在_item的title成员变量中

finalintRSS_LINK= 2;//若是link标签,记做2

finalintRSS_DESCRIPTION= 3;//若是description标签,记做3

finalintRSS_CATEGORY= 4;//若是category标签,记做4

finalintRSS_PUBDATE= 5;//若是pubdate标签,记做5,注意有两个pubdate,但我们都保存在_item的pubdate成员变量中

RSSHandler()

{

}

RSSFeed getFeed()//通过这个方法把解析结果封装在RSSFeed对象中并返回

{

return_feed;

}

//下面通过重载DefaultHandler的5个方法来实现sax解析

publicvoidstartDocument()throwsSAXException

{//这个方法在解析xml文档的一开始执行,一般我们需要在该方法中初始化解析过程中有可能用到的变量

_feed=newRSSFeed();

_item=newRSSItem();

}

publicvoidendDocument()throwsSAXException

{//这个方法在整个xml文档解析结束时执行,一般需要在该方法中返回或保存整个文档解析解析结果,但由于

//我们已经在解析过程中把结果保持在_feed中,所以这里什么也不做

}

publicvoidstartElement(String namespaceURI, String localName,String qName,

Attributes atts)throwsSAXException

{//这个方法在解析标签开始标记时执行,一般我们需要在该方法取得标签属性值,但由于我们的rss文档

//中并没有任何我们关心的标签属性,因此我们主要在这里进行的是设置标记变量currentstate,以

//标记我们处理到哪个标签

if(localName.equals("channel"))

{//channel这个标签没有任何值得我们关心的内容,所以currentstate置为0

currentstate= 0;

return;

}

if(localName.equals("image"))

{//如果是image这个标签,说明channel元素的子元素title和pubdate都已经解析出来了

//(参考xml文件结构),那么应该把它们的值从_item转移到_feed,因为我们只是图方便才

//把它们存放在_item的成员中,实际上它们应该是_feed的成员

_feed.setTitle(_item.getTitle());

_feed.setPubDate(_item.getPubDate());

}

if(localName.equals("item"))

{//若是item标签,则重新构造一个RSSItem,从而把已有(已经解析过的)item数据扔掉,当

//然事先是已经保存到_feed的itemlist集合中了

_item=newRSSItem();

return;

}

if(localName.equals("title"))

{//若是title标签,置currentstate为1,表明这是我们关心的数据,这样在characters

//方法中会把元素内容保存到_item变量中

currentstate=RSS_TITLE;

return;

}

if(localName.equals("description"))

{//若是description标签,置currentstate为3,表明这是我们关心的数据,这样在characters

//方法中会把元素内容保存到_item变量中

currentstate=RSS_DESCRIPTION;

return;

}

if(localName.equals("link"))

{//若是description标签,置currentstate为2,表明这是我们关心的数据,这样在characters

//方法中会把元素内容保存到_item变量中

currentstate=RSS_LINK;

return;

}

if(localName.equals("category"))

{//若是description标签,置currentstate为4,表明这是我们关心的数据,这样在characters

//方法中会把元素内容保存到_item变量中

currentstate=RSS_CATEGORY;

return;

}

if(localName.equals("pubDate"))

{//若是description标签,置currentstate为5,表明这是我们关心的数据,这样在characters

//方法中会把元素内容保存到_item变量中

currentstate=RSS_PUBDATE;

return;

}

currentstate= 0;//如果不是上面列出的任何标签,置currentstate为0,我们不关心

}

publicvoidcharacters(charch[],intstart,intlength)

{//这个方法在解析标签内容(即开始标记-结束标记之间的部分)时执行,一般我们在里这获取元素体内容

String theString =newString(ch,start,length);//获取元素体内容

Log.i("RSSReader","characters["+ theString +"]");

switch(currentstate)//根据currentstate标记判断这个元素体是属于我们关心的哪个元素

{

caseRSS_TITLE://若是title元素,放入_item的title属性

_item.setTitle(theString);

currentstate= 0;

break;

caseRSS_LINK://若是link元素,放入_item的link属性

_item.setLink(theString);

currentstate= 0;

break;

caseRSS_DESCRIPTION://若是description元素,放入_item的description属性

_item.setDescription(theString);

currentstate= 0;

break;

caseRSS_CATEGORY://若是category元素,放入_item的category属性

_item.setCategory(theString);

currentstate= 0;

break;

caseRSS_PUBDATE://若是pubdate元素,放入_item的pubdate属性

_item.setPubDate(theString);

currentstate= 0;

break;

default:

return;

}

}

publicvoidendElement(String namespaceURI, String localName, String qName)

throwsSAXException

{//这个方法在解析标签结束标记时执行,一般我们需要在该方法保存元素内容

if(localName.equals("item"))

{//item标签解析结束,把_item保存到_feed的itemlist属性中

_feed.addItem(_item);

return;

}

}

}

6、修改main.java,调用前面的类,从intentert获取rss列表并显示在ui上:

publicclassmainextendsActivityimplementsOnItemClickListener{

privateRSSFeedfeed=null;

privateStringtag=this.getClass().getName();

@Override

publicvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

//调用getFeed方法,从服务器取得rss提要,strings.xml中定义了r.string.RSSFEEDOFCHOICE

feed= getFeed(this.getString(R.string.RSSFEEDOFCHOICE));

//把rss内容绑定到ui界面进行显示

UpdateDisplay();

}

privateRSSFeed getFeed(String urlToRssFeed)

{//该方法通过url获得xml并解析xml内容为RSSFeed对象

try//异常处理

{

RSSHandler theRssHandler=newRSSHandler();

URL url =newURL(urlToRssFeed);

//构建Sax解析工厂

SAXParserFactory factory = SAXParserFactory.newInstance();

//使用Sax解析工厂构建Sax解析器

SAXParser parser = factory.newSAXParser();

//使用Sax解析器构建xmlReader

XMLReader xmlreader = parser.getXMLReader();

//构建自定义的RSSHandler作为xmlReader的处理器(或代理)

xmlreader.setContentHandler(theRssHandler);

//使用url打开流,并将流作为xmlReader的输入源并解析

xmlreader.parse(newInputSource(url.openStream()));

//将解析结果作为RSSFeed对象返回

returntheRssHandler.getFeed();

}

catch(Exception ee)

{

returnnull;

}

}

privatevoidUpdateDisplay()

{

TextView feedtitle = (TextView) findViewById(R.id.feedtitle);

TextView feedpubdate = (TextView) findViewById(R.id.feedpubdate);

ListView itemlist = (ListView) findViewById(R.id.itemlist);

if(feed==null)

{

feedtitle.setText("No RSS Feed Available");

return;

}

//设置channel的标题和日期

feedtitle.setText(feed.getTitle());

feedpubdate.setText(feed.getPubDate());

//构建数组适配器,用于绑定listview

ArrayAdapter<RSSItem> adapter =new

ArrayAdapter<RSSItem>(this,android.R.layout.

simple_list_item_1,feed.getAllItems());

itemlist.setAdapter(adapter);//listview绑定适配器

itemlist.setSelection(0);

itemlist.setOnItemClickListener(this);//设置itemclick事件代理

}

//itemclick事件代理方法

publicvoidonItemClick(AdapterView<?> parent, View v,intposition,longid) {

Log.d(tag,"item clicked!");

//构建一个“意图”,用于指向activity:detail

Intent itemintent =newIntent(this,detail.class);

//构建buddle,并将要传递参数都放入buddle

Bundle b =newBundle();

b.putString("title",feed.getItem(position).getTitle());

b.putString("description",feed.getItem(position).getDescription());

b.putString("link","http://www.csdn.net");// feed.getItem(position).getLink());

b.putString("pubdate",feed.getItem(position).getPubDate());

//用android.intent.extra.INTENT的名字来传递参数

itemintent.putExtra("android.intent.extra.INTENT", b);

//把意图转给子activity

this.startActivityForResult(itemintent, 0);

//this.startActivity(itemintent);

}

}

到此,程序已经可以显示第1个activity(页面)了。但由于程序使用了网络,我们还必须在AndroidManifest.xml中增加使用网络的权限:

<uses-permissionandroid:name="android.permission.INTERNET"/>

否则,程序会提示Permission denied错误。

7、打开droid draw,设计第2个activity(页面)detail.xml:

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayout

android:id="@+id/widget28"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical"

xmlns:android="http://schemas.android.com/apk/res/android"

>

<TextView

android:id="@+id/storybox"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="TextView"

android:autoLink="all"

>

</TextView>

<Button

android:id="@+id/back"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="back"

>

</Button>

</LinearLayout>

8、同时在AndroidManifest.xml中增加这个activity的声明:

<activityandroid:name=".detail">

</activity>

9、新建class detail.java:

publicclassdetailextendsActivity {

publicvoidonCreate(Bundle icicle)

{

super.onCreate(icicle);

setContentView(R.layout.detail);//加载detail.xml作为本视图

String theStory =null;

//获取调用者的“意图”

Intent startingIntent = getIntent();

if(startingIntent !=null)

{

//通过调用者意图获取对应的“参数”,字符串android.intent.extra.INTENT与调用者指定的一致

Bundle b = startingIntent.getBundleExtra("android.intent.extra.INTENT");

if(b ==null)

{

theStory ="bad bundle?";

}

else

{//读取“参数”的内容

theStory = b.getString("title") +"/n/n"+ b.getString("pubdate")

+"/n/n"+ b.getString("description").replace('/n',' ')

+"/n/nMore information:/n"+ b.getString("link");

}

}

else

{

theStory ="Information Not Found.";

}

//构建textview并用参数值设置其text

TextView db= (TextView) findViewById(R.id.storybox);

db.setText(theStory);

//构建button并设置其onclicke事件的监听者(代理)

Button backbutton = (Button) findViewById(R.id.back);

backbutton.setOnClickListener(newButton.OnClickListener()

{

publicvoidonClick(View v)

{

finish();//结束本activity,返回给调用者

}

});

}

}

更多相关文章

  1. Android性能优化之布局优化
  2. AndFix解析——(上)
  3. 在 Android(安卓)上使用 XML 传输数据(附例子程序)
  4. Android(安卓)内容提供器---创建内容提供器(元素)
  5. Android(安卓)DiskLruCache完全解析,硬盘缓存的最佳方案
  6. Android中解析XML
  7. Android中解析XML
  8. Android(安卓)使用LayerDrawable自定制SeekBar的外观
  9. Android开发之鬼迷心窍(二)

随机推荐

  1. Android(安卓)API 28 访问服务器失败 提
  2. android 中文 api (64) —— Scroller
  3. Android(安卓)加载.gif格式图片
  4. Android配置----Eclipse+BlueStacks调试A
  5. 关于Android(安卓)API,你所不知道的
  6. android dialog
  7. EditText 属性
  8. Android进入应用下载评分界面
  9. EditText属性解释
  10. Android(安卓)5.1修改底部导航栏Navigati