zoukankan      html  css  js  c++  java
  • 一个简单的android 下的rss阅读器的实现

    这篇博文前天就想写了,最近发生了很多事,而且我确实心里比较浮躁,没在状态上,因此就一直拖着.今天上午起来看看时间,都快中秋了.哎,想想时间过的还真是快.自己先前计划的在8月底的时候做出来几个小东西,到现在才做出来一个,惭愧啊.算了,不多说了.一边写博文,一边等待聘用通知吧.
    做android下的Rss阅读器,其实最核心的功能,并不是多难.先前我在博文上就已经贴出来rss核心解析的代码.
    一.先说说我做这个android rss阅读器的思路吧.
    1.界面部分:
        在顶部是一个spinner,在这个地方可以选择rss的源.底下紧跟着的是一个listview,用来显示rss源中读取出来的新闻标题.
    2.相关功能:
        1.要能手动更新rss新闻.更新rss新闻时,会根据spinner处选择的rss源的不同来更新出不同的结果.
        2.点击列表中的一条新闻,能打开对应的网页以方便使用者能查看具体的新闻
    3.功能菜单
        1.一个退出菜单,用来退出整个应用程序,这个是必须的
        2.一个更新新闻菜单,用来加载最新rss新闻
        3.一个关于菜单,用来挂广告的(呃,现在我还没考虑赚钱,先挂一个自我介绍的广告得了)
    二.实现过程
    1.rss解析
        rss解析部分先前就已经实现了.只不过当时是做的一个java版本的没有界面的一个rss解析器,还不能称为阅读器
    2.界面实现
        在主界面的布局文件上:
        定义了一个spinner和listview元素

       1: <?xml version="1.0" encoding="utf-8"?>
       2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       3:     android:orientation="vertical" android:layout_width="fill_parent"
       4:     android:layout_height="fill_parent">
       5:     <TextView android:layout_width="fill_parent"
       6:         android:layout_height="wrap_content" android:text="@string/selectTip" />
       7:     <Spinner android:id="@+id/rssSourceSpinner"
       8:         android:layout_width="fill_parent" android:layout_height="wrap_content" />
       9:     <LinearLayout android:id="@+id/list_ll"
      10:         android:layout_width="fill_parent" android:layout_height="fill_parent">
      11:         <ListView android:id="@+id/android:list" android:layout_width="fill_parent"
      12:             android:layout_height="wrap_content" />
      13:     </LinearLayout>
      14: </LinearLayout>


        同时在另外一个布局文件中定义了listview中的每行的元素的格式布局

       1: <?xml version="1.0" encoding="utf-8"?>
       2: <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
       3:     android:id="@+id/title" android:layout_width="wrap_content" 
       4:     android:layout_height="wrap_content"/>


    3.菜单布置
        菜单实现上,专门在res下建立了menu文件夹,在其下创建menu.xml,里面定义了三个菜单元素,分别对应着更新rss新闻,关于和退出

       1: <?xml version="1.0" encoding="UTF-8"?>
       2: <menu xmlns:android="http://schemas.android.com/apk/res/android">
       3: <item android:id="@+id/refresh" android:title="更新新闻"></item>
       4: <item android:id="@+id/about" android:title="关于"></item>
       5: <item android:id="@+id/exit" android:title="退出"></item>
       6: </menu>

    4.前后端交互部分实现

       1: package com.leipei.android;
       2:  
       3: import java.util.ArrayList;
       4: import java.util.List;
       5:  
       6: import com.leipei.rss.Message;
       7: import com.leipei.rss.RssSaxParser;
       8:  
       9: import android.app.AlertDialog;
      10: import android.app.ListActivity;
      11: import android.content.DialogInterface;
      12: import android.content.DialogInterface.OnClickListener;
      13: import android.content.Intent;
      14: import android.net.Uri;
      15: import android.os.Bundle;
      16: import android.view.Gravity;
      17: import android.view.Menu;
      18: import android.view.MenuInflater;
      19: import android.view.MenuItem;
      20: import android.view.View;
      21: import android.widget.AdapterView;
      22: import android.widget.AdapterView.OnItemSelectedListener;
      23: import android.widget.ArrayAdapter;
      24: import android.widget.ListView;
      25: import android.widget.Spinner;
      26: import android.widget.Toast;
      27:  
      28: public class RssMainActivity extends ListActivity {
      29:  
      30:     private Spinner rssSelectSpinner;
      31:     private String[] rssurlarray;
      32:     private String currentRssurl;
      33:     private List<Message> messages;
      34:  
      35:     /** Called when the activity is first created. */
      36:     @Override
      37:     public void onCreate(Bundle savedInstanceState) {
      38:         super.onCreate(savedInstanceState);
      39:         setContentView(R.layout.main);
      40:         rssSelectSpinner = (Spinner) findViewById(R.id.rssSourceSpinner);
      41:         loadSpinner();
      42:         initRssUrlArray();
      43:     }
      44:  
      45:     /*
      46:      * 初始化Rss数据源的url数组 从先前定义好的rss源的xml文件中获取rss源的名称
      47:      */
      48:     public void initRssUrlArray() {
      49:         this.rssurlarray = getResources().getStringArray(R.array.source_url);
      50:     }
      51:  
      52:     /*
      53:      * 初始化rss源的下拉列表
      54:      */
      55:     public void loadSpinner() {
      56:         ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter
      57:                 .createFromResource(this, R.array.source_title,
      58:                         R.layout.newstitle);
      59:         spinnerAdapter
      60:                 .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
      61:         rssSelectSpinner.setAdapter(spinnerAdapter);
      62:         rssSelectSpinner
      63:                 .setOnItemSelectedListener(new OnItemSelectedListener() {
      64:  
      65:                     public void onItemSelected(AdapterView<?> parent,
      66:                             View view, int pos, long id) {
      67:                         parent.setVisibility(View.VISIBLE);
      68:                         RssMainActivity.this.currentRssurl = RssMainActivity.this.rssurlarray[pos];
      69:                     }
      70:  
      71:                     public void onNothingSelected(AdapterView parent) {
      72:                         // Do nothing.
      73:                     }
      74:                 });
      75:     }
      76:  
      77:     /*
      78:      * (non-Javadoc)
      79:      * 
      80:      * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
      81:      * 初期只做三个菜单项,分别是更新rss,关于和退出
      82:      */
      83:     @Override
      84:     public boolean onCreateOptionsMenu(Menu menu) {
      85:         MenuInflater inflater = getMenuInflater();
      86:         inflater.inflate(R.menu.menu, menu);
      87:         return true;
      88:     }
      89:  
      90:     @Override
      91:     public boolean onOptionsItemSelected(MenuItem item) {
      92:         int item_id = item.getItemId();
      93:         switch (item_id) {
      94:         // 如果是点击了更新菜单,则重新加载一个rss新闻
      95:         case R.id.refresh:
      96:             this.loadRss();
      97:             break;
      98:         // 如果是点击了关于菜单,则弹出对话框,在其中显示一些关于我的信息,初期不挂赢利性广告
      99:         case R.id.about:
     100:             AlertDialog.Builder aboutDialog = new AlertDialog.Builder(this);
     101:             aboutDialog.setTitle(R.string.aboutme);
     102:             aboutDialog.setMessage(R.string.about_info);
     103:             aboutDialog.setPositiveButton("确定", new OnClickListener() {
     104:  
     105:                 @Override
     106:                 public void onClick(DialogInterface dialog, int which) {
     107:                     dialog.dismiss();
     108:                 }
     109:             });
     110:             aboutDialog.create().show();
     111:             break;
     112:         // 如果点击的是退出菜单,则退出Activity,由于整个应用程序只有一个Activity,则退出了应用程序
     113:         case R.id.exit:
     114:             this.finish();
     115:             break;
     116:         }
     117:         return true;
     118:     }
     119:  
     120:     /*
     121:      * 根据现在选中的spinner来加载对应的新闻
     122:      */
     123:     public void loadRss() {
     124:         if (this.currentRssurl == null) {
     125:             showTips("chose a rss url first!");
     126:         } else {
     127:             RssSaxParser rssparser = new RssSaxParser(this.currentRssurl);
     128:             System.out.println(this.currentRssurl);
     129:             this.messages = rssparser.parse();
     130:  
     131:             System.out.println("messages.size()" + this.messages.size());
     132:             List<String> titles = new ArrayList<String>(this.messages.size());
     133:             for (Message msg : this.messages) {
     134:                 titles.add(msg.getTitle());
     135:             }
     136:             ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
     137:                     R.layout.newstitle, titles);
     138:             this.setListAdapter(adapter);
     139:         }
     140:     }
     141:  
     142:     /*
     143:      * 显示一些提示信息
     144:      */
     145:     public void showTips(String tip) {
     146:         Toast toast = Toast.makeText(this, tip, Toast.LENGTH_SHORT);
     147:         toast.setGravity(Gravity.CENTER, 0, 10);
     148:         toast.show();
     149:     }
     150:  
     151:     /*
     152:      * (non-Javadoc)
     153:      * 
     154:      * @see android.app.ListActivity#onListItemClick(android.widget.ListView,
     155:      * android.view.View, int, long)
     156:      * 重写ListActivity的方法,当listview中的某条新闻被点击选中,则打开对应新闻的url链接
     157:      */
     158:     @Override
     159:     protected void onListItemClick(ListView l, View v, int position, long id) {
     160:         super.onListItemClick(l, v, position, id);
     161:         Intent viewMessage = new Intent(Intent.ACTION_VIEW,
     162:                 Uri.parse(this.messages.get(position).getLink()
     163:                         .toExternalForm()));
     164:         this.startActivity(viewMessage);
     165:     }
     166: }

    三.一些补充
    1.rss解析的额外改动   
    现在需要注意的是,因为android虚拟机的默认支持的编码和我本机的不一样,导致这样一个结果:

       1: SAXParser parser = factory.newSAXParser();
       2: RssHandler myxmlhandler = new RssHandler();
       3: parser.parse(this.rssurl, myxmlhandler);
    这三行代码执行的结果是,logcat报错"not well-formed".解决这个问题的办法是,指定sax 解析的xml流的编码:
       1: URL url=new URL(this.rssurl);
       2: InputStream inputStream=url.openStream();
       3: Charset charset = Charset.forName("GBK");   // 在此处声明GBK方式
       4: Reader r = new InputStreamReader(inputStream, charset);
       5: InputSource source = new InputSource(r);
       6: parser.parse(source,myxmlhandler);
       7: inputStream.close();
    四.上图收尾
    1.加载QQ国内新闻
    image
    2.关于我
    image
  • 相关阅读:
    抽象代数学习笔记
    WC2021 游记
    简单的数学题
    前缀和公式
    杜教筛
    [模板]BZOJ4756线段树合并
    SPOJ 694
    bzoj1367 可并堆
    莫比乌斯反演(理论)
    es6 Set数据结构
  • 原文地址:https://www.cnblogs.com/leipei2352/p/2170096.html
Copyright © 2011-2022 走看看