我修改了Head First Android
显示的代码,以便从NASA的每日图像中获取RSS源。我决定使用AsyncTask
来获取数据,然后将其传递回UI线程进行更新。但是,这里有一些奇怪的结果
右边的那个是点击按钮后的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);
}
//------------------------------------------------------------------------------
}
}
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;}
//------------------------------------------------------------------------------
}
我该如何解决这个问题?
答案 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;}
}