I have modified the code from Head First Android
display to get the RSS feeds from NASA's Image of the Day. I decided to use AsyncTask
to get the data and then pass it back to the UI thread to update. However, there is some strange results here.
The one on the right is the UI after clicking the button. Strange enough.
Below is my code for the 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;}
//------------------------------------------------------------------------------
}
How do I go about solving this?