Android不解析RSS提要

时间:2013-07-22 23:41:56

标签: java android rss android-asynctask

我修改了Head First Android显示的代码,以便从NASA的每日图像中获取RSS源。我决定使用AsyncTask来获取数据,然后将其传递回UI线程进行更新。但是,这里有一些奇怪的结果 enter image description here enter image description here 右边的那个是点击按钮后的UI。很奇怪。

以下是Activity

的代码
package com.example.nasadailyimage;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;

public class NasaDailyImage extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button b = (Button) findViewById(R.id.button);
        //get feeds only when button is clicked!
        b.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                new AsyncRetriever().execute(new IotdHandler()); // Get the feeds !!
            }
        });
    }
//------------------------------------------------------------------------------
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.nasa_daily_image, menu);
        return true;
    }
//------------------------------------------------------------------------------
    /**
     * This method is called by onPostExecute and is used to update the UI.
     * It first checks if an error occured while parsing the RSS feed.
     * If yes, it displays "Error" in all TextViews and displays an 
     * AlertDialog.
     * Else, it displays the new data.
     * @param hasErrorOccured
     * @param reply
     */
    public synchronized void resetDisplay(boolean hasErrorOccured,IotdHandler reply){
        if(hasErrorOccured){

            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                    this);

                // set title
                alertDialogBuilder.setTitle("An error has occured while retrieving feed");

                // set dialog message
                alertDialogBuilder
                    .setMessage("Click to exit")
                    .setCancelable(false)
                    .setNegativeButton("Exit",new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog,int id) {
                            // if this button is clicked, just close
                            // the dialog box and do nothing
                            dialog.cancel();
                        }
                    });
                // create alert dialog
                AlertDialog alertDialog = alertDialogBuilder.create();

                // show it
                alertDialog.show();


            TextView textHeader = (TextView) findViewById(R.id.textHeader);
            TextView date = (TextView) findViewById(R.id.date);
            ImageView img = (ImageView) findViewById(R.id.image);
            TextView desc = (TextView) findViewById(R.id.desc);

            textHeader.setText("Error");
            date.setText("Error");
            desc.setText("Error");

            return;
        }else{
            TextView textHeader = (TextView) findViewById(R.id.textHeader);
            TextView date = (TextView) findViewById(R.id.date);
            ImageView img = (ImageView) findViewById(R.id.image);
            TextView desc = (TextView) findViewById(R.id.desc);

            textHeader.setText(reply.getTitle());
            date.setText(reply.getDate());
            img.setImageBitmap(reply.getImage());
            desc.setText(reply.getDescription());
        }
    }
//------------------------------------------------------------------------------
    /**
     * This class retrieves data from the RSS feed. I am using AsyncTask because
     * it is not a good practice to block the UI thread while performing 
     * network operations.
     *
     */
    class AsyncRetriever extends AsyncTask<IotdHandler,Void,IotdHandler>{

        @Override
        protected IotdHandler doInBackground(IotdHandler... arg0) {
            IotdHandler handler = arg0[0];
            handler.processFeed(); // get the RSS feed data !
            return handler;
        }
//------------------------------------------------------------------------------    
        @Override
        protected void onPostExecute(IotdHandler fromInBackground){
            resetDisplay(fromInBackground.errorOccured,fromInBackground);
        }
//------------------------------------------------------------------------------
    }
}  

IotdHandler

public class IotdHandler extends DefaultHandler{
    private String url = "http://www.nasa.gov/rss/image_of_the_day.rss";
    /**
     * Since the events  get called differently, you need to keep
     * a track of which tag you are in.
     */

    private boolean inTitle = false;
    private boolean inDescription = false;
    private boolean inItem = false;
    private boolean inDate = false;
    public boolean errorOccured = false;
    boolean firstItemHit = false;

    private Bitmap image = null;
    private String title = null;
    private StringBuffer description = new StringBuffer();
    private String date = null;
//------------------------------------------------------------------------------
    public void processFeed(){
        try{
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            InputStream stream = new URL(url).openStream();
            parser.parse(stream, this);
        }catch(Exception e){
            errorOccured = true;
        }
    }
//------------------------------------------------------------------------------
    private Bitmap getBitmap(String url){
        try{
            HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection();
            con.setDoInput(true);
            con.connect();
            InputStream input = con.getInputStream();
            Bitmap bmp = BitmapFactory.decodeStream(input);
            input.close();
            return bmp;
        }catch(Exception e){
            errorOccured = true;
            return null;
        }
    }
//------------------------------------------------------------------------------
    @Override
    public void startElement(String uri,String localName,String qName, 
            Attributes attr) throws SAXException{
            if(localName.equals("item")){ 
                if(localName.equals("title")){inTitle = true;}
                if(localName.equals("description")){inDescription = true;}
                if(localName.equals("pubDate")){inDate = true;}
                if(localName.equals("enclosure")){
                    String url = attr.getValue(0);
                    getBitmap(url);
                }
            }

    }
//------------------------------------------------------------------------------
    @Override
    public void characters(char[] ch,int start,int length){
        String charData = new String(ch);
            if(inTitle){
                title = charData;
            }
            if(inDescription){
                description.append(charData);
            }
            if(inDate){
                date = charData;
            }
    }
//------------------------------------------------------------------------------
    public Bitmap getImage(){return image;}
    public String getTitle(){return title;}
    public StringBuffer getDescription(){return description;}
    public String getDate(){return date;}
//------------------------------------------------------------------------------
}

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

我认为问题出在你的IotdHandler

中的startElement函数中

基本上你正在检查localName是否等于“item”,然后在if if块中检查localName是否等于“title”然后是“description”等。这些内部if语句都不会是真的,因为只有当localName等于“item”

时才会对它们进行评估

您可以删除支票

  

如果(localName.equals( “项目”))

所有这些一起那些内部if语句有可能评估为true或者如果你想确保标题,描述等的匹配在项目节点内你可以将它改为:

        if(localName.equals("item")){inItem = true;}
        if(inItem){
            if(localName.equals("title")){inTitle = true;}
            if(localName.equals("description")){inDescription = true;}
            if(localName.equals("pubDate")){inDate = true;}
            if(localName.equals("enclosure")){
                String url = attr.getValue(0);
                getBitmap(url);
            }
        }

虽然你使用所有那些布尔值确定你是否在一个区块中,但是你应该确保通过覆盖endElement函数将它们设置为false ala

@Override
public void endElement(String uri,String localName,String qName) throws SAXException{
        if(localName.equals("item")){inItem = false;}
        if(localName.equals("title")){inTitle = false;}
        if(localName.equals("description")){inDescription = false;}
        if(localName.equals("pubDate")){inDate = false;}
}