模仿网易新闻客户端(RSS版)(二)
一、摘要
继上一篇博客《模仿网易新闻客户端(一)》之后,笔者继续开发我们自己的“网易新闻客户端”,由于找不到现成的url新闻链接地址,所以这里就用RSS订阅所提供的url,这里所用到的链接仍然是网易新闻中心的RSS地址http://www.163.com/rss/,然后通过解析xml内容,以ListView的方式呈现在手机界面上。还有一个问题,因为RSS所提供的xml资源里面,没有对应item的图片,所以,ListView里面每一个Item都没有图片,这点有点遗憾,但也没事,实现其功能就行了。废话不多说,老惯例,先看效果图
二、效果截图
三、解析RSS
首先,先大概地看一下RSS所提供XML的数据结构,下面是一个RSS文件结构示例
<?xml version="1.0" encoding="GBK"?> <?xml-stylesheet type="text/css" href="http://news.163.com/css/allrss.css"?> <rss version="2.0"> <channel> <title>网易头条新闻</title> <link>http://news.163.com/</link> <description>网易头条新闻</description> <pubDate>Mon, 2 Apr 2012 01:07:10 GMT</pubDate> <lastBuildDate>Mon, 2 Apr 2012 01:07:10 GMT</lastBuildDate> <item id="1"> <title>...</title> <link>http://news.163.com/12/0402/08/7U2TBKQF0001124J.html</link> <description>......</description> <pubDate>2012-04-02 09:07:10</pubDate> </item> </channel> </rss>
了解了有哪些节点,下面来编写元数据类RSSItem.java
package com.and.netease.rss; public class RSSItem { private String title; private String link; private String description; private String pubDate; public RSSItem() { super(); } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getLink() { return link; } public void setLink(String link) { this.link = link; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getPubDate() { return pubDate; } public void setPubDate(String pubDate) { this.pubDate = pubDate; } @Override public String toString() { return "RSSItem [title=" + title + ", link=" + link + ", description=" + description + ", pubDate=" + pubDate + "]"; } }
紧接着编写解析XML的Handler类:RSSHandler.java
package com.and.netease.rss; import java.util.ArrayList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import android.text.Html; public class RSSHandler extends DefaultHandler { private List<RSSItem> list; private RSSItem item; private String tag = ""; private StringBuffer buffer; @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); if(item!=null){ String data = new String(ch,start,length); if(tag.equals("title")){ item.setTitle(data); }else if(tag.equals("link")){ item.setLink(data); }else if(tag.equals("description")){ // item.setDescription(data); buffer.append(Html.fromHtml(data)); }else if(tag.equals("pubDate")){ item.setPubDate(data); } } } @Override public void endDocument() throws SAXException { super.endDocument(); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if(localName.equals("item")){ item.setDescription(buffer.toString()); list.add(item); item = null; buffer = null; } tag = ""; } @Override public void startDocument() throws SAXException { super.startDocument(); list = new ArrayList<RSSItem>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); if(localName.equals("item")){ item = new RSSItem(); buffer = new StringBuffer(); } tag = localName; } public List<RSSItem> getData(){ return list; } }
注意:在存description的值的时候,可能会出问题,有可能读取出来的全是省略号,因为第一次读取到数据,存入了相应的RSSItem实例变量中,第二次又读取到省略号,再存入当前的RSSItem实例中,造成最后只有第二次存入的值,因为它前面的文字和后面的省略号不是一次读取完的,所以我这里用了一个StringBuffer来存它,之后一次性地存入到当拉RSSItem中。当然有些提供的RSS源代码中不是这样的。具体需要自己测试一下才好。
当然,这里所解析的所有URL地址放在一个常量类里面的,开始本想放String.xml文件中,但是地址里面有特殊字符,为了简便,就专门定义了一个常量类用来存放URL地址,如下CONST.java
package com.and.netease; public class CONST { public static final String URL_NEWS_TOP = "http://news.163.com/special/00011K6L/rss_newstop.xml"; public static final String URL_NEWS_SPORT = "http://sports.163.com/special/00051K7F/rss_sportslq.xml"; public static final String URL_NEWS_PLAY = "http://ent.163.com/special/00031K7Q/rss_toutiao.xml"; public static final String URL_NEWS_FINANCE = "http://money.163.com/special/00252EQ2/yaowenrss.xml"; public static final String URL_NEWS_SCIENCE = "http://tech.163.com/special/000944OI/headlines.xml"; //国内 public static final String URL_NEWS_DOMESTIC = "http://news.163.com/special/00011K6L/rss_gn.xml"; //军事 public static final String URL_NEWS_MILITARY = "http://news.163.com/special/00011K6L/rss_war.xml"; //国际 public static final String URL_NEWS_INTERNATIONAL = "http://news.163.com/special/00011K6L/rss_gj.xml"; //社会 public static final String URL_NEWS_COMMUNITY = "http://news.163.com/special/00011K6L/rss_sh.xml"; //深度 public static final String URL_NEWS_DEPTH = "http://news.163.com/special/00011K6L/rss_hotnews.xml"; //彩票 public static final String URL_NEWS_TICKET = "http://sports.163.com/special/00051K7F/rss_sportscp.xml"; //电影 public static final String URL_NEWS_FILM = "http://ent.163.com/special/00031K7Q/rss_entmovie.xml"; //音乐 public static final String URL_NEWS_MUSIC = "http://ent.163.com/special/00031K7Q/rss_entmusic.xml"; //IT public static final String URL_NEWS_IT = "http://tech.163.com/special/000944OI/kejiyejie.xml"; //汽车 public static final String URL_NEWS_CAR = "http://auto.163.com/special/00081K7D/rsstoutiao.xml"; //数码 public static final String URL_NEWS_DIGITAL = "http://tech.163.com/digi/special/00161K7K/rss_digixj.xml"; //网易话题 public static final String URL_TOPIC = "http://news.163.com/special/00011K6L/rss_newsspecial.xml"; //网易图片 public static final String URL_PICTURE = "http://news.163.com/special/00011K6L/rss_photo.xml"; //网易跟帖 public static final String URL_FOLLOW = ""; //网易投票 public static final String URL_VOTE = ""; }
后面的网易跟帖和投票,我实在找不到合适的URL地址了,所以就都用的网易图片的URL,因为里面我没有涉及到跟帖和投票的操作。如上最后一张图片所示。
四、关于Tab(新闻)页面的讲解
由于RSS格式的限制,所以里面的各个页面大体框架类似,下面只大概讲解一下“新闻”页面。它是TabHost里面的其中一个页面,在这个页面中涉及到另外几个页面,如“头条”、“体育”、“娱乐”、“财经”等一些,所以这个页面让它继承自ActivityGroup类,在这个ActivityGroup类里面可以管理很多的Activity。那要怎样把一个Activity添加到ActivityGroup中来呢?
intent = new Intent(TabNewsActivity.this, TabNewsTopActivity.class); page = getLocalActivityManager().startActivity("activity1", intent).getDecorView(); LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); layout_news_main.addView(page, params);
viewSwitcher = (ViewSwitcher) findViewById(R.id.viewswitcher_news_top); listView = new MyListView(this); ... viewSwitcher.addView(listView); viewSwitcher.addView(getLayoutInflater().inflate(R.layout.layout_progress_page, null)); viewSwitcher.showNext();
完整代码TabNewsTopActivity.java
package com.and.netease; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; import java.util.List; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import com.and.netease.MyListView.OnRefreshListener; import com.and.netease.rss.RSSHandler; import com.and.netease.rss.RSSItem; import android.app.Activity; import android.content.Intent; import android.graphics.Color; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import android.widget.ViewSwitcher; public class TabNewsTopActivity extends Activity { MyListView listView; List<RSSItem> list; RSSHandler rssHandler; MyAdapter adapter; ViewSwitcher viewSwitcher; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_news_top); setTheme(android.R.style.Theme_Translucent_NoTitleBar); initViews(); rssHandler = new RSSHandler(); requestRSSFeed(); } private void initViews() { viewSwitcher = (ViewSwitcher) findViewById(R.id.viewswitcher_news_top); listView = new MyListView(this); listView.setCacheColorHint(Color.argb(0, 0, 0, 0)); ImageView testView = new ImageView(this); testView.setImageResource(R.drawable.temp); listView.addHeaderView(testView); listView.setonRefreshListener(refreshListener); viewSwitcher.addView(listView); viewSwitcher.addView(getLayoutInflater().inflate(R.layout.layout_progress_page, null)); viewSwitcher.showNext(); listView.setOnItemClickListener(listener); } private OnRefreshListener refreshListener = new OnRefreshListener() { @Override public void onRefresh() { // TODO Auto-generated method stub new AsyncTask<Void, Void, Void>() { protected Void doInBackground(Void... params) { try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void result) { adapter.notifyDataSetChanged(); listView.onRefreshComplete(); } }.execute(null); } }; private void requestRSSFeed() { Thread t = new Thread() { @Override public void run() { super.run(); try { URL url = new URL(CONST.URL_NEWS_TOP); URLConnection con = url.openConnection(); con.connect(); InputStream input = con.getInputStream(); SAXParserFactory fac = SAXParserFactory.newInstance(); SAXParser parser = fac.newSAXParser(); XMLReader reader = parser.getXMLReader(); reader.setContentHandler(rssHandler); Reader r = new InputStreamReader(input, Charset.forName("GBK")); reader.parse(new InputSource(r)); list = rssHandler.getData(); // for (RSSItem rss : list) { // System.out.println(rss); // } if (list.size() == 0) { handler.sendEmptyMessage(-1); } else { handler.sendEmptyMessage(1); } } catch (Exception e) { e.printStackTrace(); } } }; t.start(); } Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { if (msg.what == 1) { adapter = new MyAdapter(); listView.setOnItemClickListener(listener); listView.setAdapter(adapter); viewSwitcher.showPrevious(); listView.onRefreshComplete(); } }; }; private OnItemClickListener listener = new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if(position==1){ return; } Intent intent = new Intent(TabNewsTopActivity.this, NewsContentActivity.class); intent.putExtra("content_url", list.get(position-2).getLink()); TabNewsTopActivity.this.startActivityForResult(intent, position); } }; private class MyAdapter extends BaseAdapter { @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = getLayoutInflater().inflate(R.layout.layout_news_top_item, null); holder.tv_date = (TextView) convertView.findViewById(R.id.tv_date_news_top_item); holder.tv_title = (TextView) convertView.findViewById(R.id.tv_title_news_top_item); holder.tv_Description = (TextView) convertView.findViewById(R.id.tv_description_news_top_item); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.tv_date.setText(list.get(position).getPubDate()); holder.tv_title.setText(list.get(position).getTitle()); holder.tv_Description.setText(list.get(position).getDescription()); return convertView; } } public static class ViewHolder { TextView tv_date; TextView tv_title; TextView tv_Description; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { System.out.println("返回"); super.onActivityResult(requestCode, resultCode, data); } }
五、具体新闻内容
package com.and.netease; import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ImageButton; import android.widget.ViewSwitcher; public class NewsContentActivity extends Activity { ImageButton btn_back; WebView webView; String content_url; ViewSwitcher viewSwitcher; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_newscontent); initViews(); } private void initViews() { btn_back = (ImageButton) findViewById(R.id.btn_newscontent_back); btn_back.setOnClickListener(listener); viewSwitcher = (ViewSwitcher) findViewById(R.id.viewSwitcher); content_url = getIntent().getStringExtra("content_url"); webView = new WebView(this); // 向ViewSwitcher中添加两个View,用来切换 viewSwitcher.addView(webView); viewSwitcher.addView(getLayoutInflater().inflate( R.layout.layout_progress_page, null)); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); webView.setWebViewClient(client); webView.loadUrl(content_url); } private WebViewClient client = new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); viewSwitcher.showPrevious(); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); viewSwitcher.showNext(); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return super.shouldOverrideUrlLoading(view, url); } }; private OnClickListener listener = new OnClickListener() { @Override public void onClick(View v) { NewsContentActivity.this.setResult(RESULT_OK); NewsContentActivity.this.finish(); } }; public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { NewsContentActivity.this.setResult(RESULT_OK); NewsContentActivity.this.finish(); } }; }
六、总结
模仿网易新闻客户端(RSS版)(二)相关推荐
- 模仿网易新闻客户端的滚动菜单
模仿网易新闻客户端的滚动菜单,点击菜单的时候有放大标题的动画效果.demo地址:https://github.com/BigHub/ScrollMenuViewTest 需要用到facebook的开源 ...
- 模仿网易新闻客户端(RSS版)(一)
一.摘要 这几天找工作闲来没事,偶然在一个论坛上面看到有人模拟网易新闻客户端首页顶部那个组件效果,一时兴起,也来自己动手完整地模拟一个,包括顶部的特效组件和底部的类似于TabHost的组件.下面就动手 ...
- Android Studio精彩案例(四)《DrawerLayout使用详解仿网易新闻客户端侧边栏 》
转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 为了提高兴趣,咱们开头先看看最终要实现什么样的效果: 侧拉菜单在Android应用中非常常见,它的实现方式太多了,今天我们就说说使用G ...
- android平台上线,网易新闻客户端3.0版iOS、Android平台正式上线
网易科技讯 12月3日消息,网易新闻客户端3.0版在"2012网易移动媒体高峰论坛"第一次对外亮相,今日3.0版正式在ios和android平台同步上线,目前,用户已可在各大应用商 ...
- [转]网易新闻客户端为什么开始在北京市区的地铁、公交站牌大批量投放广告?...
一.可能是网易新闻客户端取得了不可思议的成功,潜力巨大,引起了网易的重视. 二.可能是京城学生上班族群体的智能手机普及率高,拓展市场. -------------------------------- ...
- Android 开源框架ViewPageIndicator 和 ViewPager 仿网易新闻客户端Tab标签
转载请注明出处:http://blog.csdn.net/xiaanming/article/details/10766053 之前用JakeWharton的开源框架ActionBarSherl ...
- Android SlidingMenu 仿网易新闻客户端布局
前面两篇文章中的SlidingMenu都出现在左侧,今天来模仿一下网易新闻客户端左右两边都有SlidingMenu的效果,以下是网易新闻客户端效果: 不扯闲话了,直接进入正题吧 frame_conte ...
- Android高仿网易新闻客户端之首页
关于实现网易新闻客户端的界面,以前写过很多博客,请参考: Android实现网易新闻客户端效果 Android实现网易新闻客户端侧滑菜单(一) Android实现网易新闻客户端侧滑菜单(二) 今天用V ...
- 视频教程-Flutter布局实战网易新闻客户端-flutter
Flutter布局实战网易新闻客户端 Flutter书籍作者.曾任职于多家互联网大型企业,担任移动端项目技术负责人,主导研发和攻关技术难题,项目涉及教育.金融.医疗.交通.车载设备.智能家居等众多领域 ...
最新文章
- WEB开发者八项注意
- NodeJS、NPM安装配置与测试步骤(windows版本)
- ProtoBuf开发者指南
- 函数式编程是啥玩意?map() reduce()(reduce()函数将数字列表转换为x进制数字)闭包、装饰器、偏函数
- BZOJ 2957: 楼房重建
- list 置顶元素_java集合指定元素排序:最前,按照提供的顺序排序?求算法
- 树的遍历-Preorde Traversal,Inorder Traversal,Postoder Traversal
- linux下c语言俄罗斯方块,c语言做俄罗斯方块
- JDK源码(19)-Package
- 关于服务限流的一些思考
- 安卓手机管理软件_日程管理软件哪个好?
- 【bzoj1085】【SCOI2005】【骑士精神】
- mysql对象资源管理器在哪里_文件资源管理器在哪
- 硬盘显示无法访问由于IO设备错误的文件找到办法
- java 苹果支付(内购)
- 大麦网滑块验证码自动识别
- 使用Zeplin 过程中 TextView不显示的问题?
- 【讲座回顾】不会被AI取代的人
- linux18安装anyconnect4.9遇到I/O问题
- 计算机网络原理 - 概述
热门文章
- 通过Validation框架检查请求参数的基本格式
- Go语言基础入门(处理JSON)
- 【汇正财经】1.3日盘面回顾和行情解析
- Ubuntu linux中怎么查看自己的串口连接情况
- 信息大爆炸时代的生存指南(2):我们的基本信息素养
- 零基础学平面设计还学美工设计比较有前途?
- Unity制作游戏中改名系统(第一次改名免费、改名提示、充值获得改名次数等 )
- buu做题笔记——[WUSTCTF2020]朴实无华[BSidesCF 2020]Had a bad day
- ModelMapper
- openeuler 22.03 制作openssh9.3p1 rpm升级包和升级实战