RSS Parser with CustomAdapter using AsyncTask - android

Hi below is my working code to parse RSS and populate it in ListView, but I want to add CustomAdapter rather than simple Adapter, so that I can add an ImageView in ListView and design my own ListView. Can someone help with code.
SocialFeeds.Java
public class SocialFeeds extends Activity {
// A reference to the local object
private SocialFeeds local;
/**
* This method creates main application view
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set view
setContentView(R.layout.tweet);
// Set reference to this activity
local = this;
GetRSSDataTask task = new GetRSSDataTask();
// Start download RSS task
task.execute("https:url");
// Debug the thread name
Log.d("ITCRssReader", Thread.currentThread().getName());
}
private class GetRSSDataTask extends AsyncTask<String, Void, List<RssItem>> {
private final ProgressDialog dialog = new ProgressDialog(SocialFeeds.this);
#Override
protected List<RssItem> doInBackground(String... urls) {
// Debug the task thread name
Log.d("ITCRssReader", Thread.currentThread().getName());
try {
// Create RSS reader
RssReader rssReader = new RssReader(urls[0]);
// Parse RSS, get items
return rssReader.getItems();
} catch (Exception e) {
Log.e("ITCRssReader", e.getMessage());
}
return null;
}
#Override
protected void onPreExecute() {
dialog.setMessage("Please Wait.");
dialog.setCancelable(true);
dialog.show();
}
#Override
protected void onPostExecute(List<RssItem> result) {
if (dialog.isShowing())
{
dialog.dismiss();
}
// Get a ListView from main view
ListView itcItems = (ListView) findViewById(R.id.list);
// Create a list adapter
ArrayAdapter<RssItem> adapter = new ArrayAdapter<RssItem>(local,android.R.layout.simple_list_item_1, result);
// Set list adapter for the ListView
itcItems.setAdapter(adapter);
// Set list view item click listener
itcItems.setOnItemClickListener(new ListListener(result, local));
}
}
}
ListListener.java
public class ListListener extends Activity implements OnItemClickListener {
// List item's reference
List<RssItem> listItems;
// Calling activity reference
Activity activity;
AlertDialog.Builder alert;
WebView wv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public ListListener(List<RssItem> aListItems, Activity anActivity) {
listItems = aListItems;
activity = anActivity;
}
/**
* Start a browser with url from the rss item.
*/
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
/*Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(listItems.get(pos).getLink()));
activity.startActivity(i);*/
}
}
RssParseHandler.java
public class RssParseHandler extends DefaultHandler {
private List<RssItem> rssItems;
// Used to reference item while parsing
private RssItem currentItem;
// Parsing title indicator
private boolean parsingTitle;
// A buffer used to build current title being parsed
private StringBuffer currentTitleSb;
// Parsing pubDate indicator
private boolean parsingpubDate;
// A buffer used to build current pubDate being parsed
private StringBuffer currentpubDateSb;
// Parsing description indicator
private boolean parsingDescription;
// A buffer used to build current description being parsed
private StringBuffer currentDescriptionSb;
// Parsing link indicator
private boolean parsingLink;
public RssParseHandler() {
rssItems = new ArrayList<RssItem>();
}
public List<RssItem> getItems() {
return rssItems;
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("item".equals(qName)) {
currentItem = new RssItem(0, qName, qName, qName);
} else if ("title".equals(qName)) {
parsingTitle = true;
currentTitleSb = new StringBuffer();
}
else if ("pubDate".equals(qName)) {
parsingpubDate = true;
currentpubDateSb = new StringBuffer();
}
else if ("description".equals(qName)) {
parsingDescription = true;
currentDescriptionSb = new StringBuffer();
}
else if ("link".equals(qName)) {
parsingLink = true;
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("item".equals(qName)) {
rssItems.add(currentItem);
currentItem = null;
}
else if ("title".equals(qName)) {
parsingTitle = false;
// Set item's title when we parse item->title tag not the channel title tag
if (currentItem != null) {
// Set item's title here
currentItem.setTitle(currentTitleSb.toString());
}
}
else if ("pubDate".equals(qName)) {
parsingpubDate = false;
// Set item's pubDate when we parse item->pubDate tag not the channel pubDate tag
if (currentItem != null) {
// Set item's pubDate here
currentItem.setpubDate(currentpubDateSb.toString());
}
}
else if ("description".equals(qName)) {
parsingDescription = false;
// Set item's description when we parse item->description tag not the channel description tag
if (currentItem != null) {
// Set item's description here
currentItem.setDescription(currentDescriptionSb.toString());
}
}
else if ("link".equals(qName)) {
parsingLink = false;
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (parsingTitle) {
if (currentItem != null) {
// Here we append the title to the buffer due to network issues.
// Sometimes this characters method is called multiple times for a tag contents.
currentTitleSb.append(new String(ch, start, length));
}
}
if (parsingpubDate) {
if (currentItem != null) {
// Here we append the pubDate to the buffer due to network issues.
// Sometimes this characters method is called multiple times for a tag contents.
currentpubDateSb.append(new String(ch, start, length));
}
}
if (parsingDescription) {
if (currentItem != null) {
// Here we append the description to the buffer due to network issues.
// Sometimes this characters method is called multiple times for a tag contents.
currentDescriptionSb.append(new String(ch, start, length));
}
}
else if (parsingLink) {
if (currentItem != null) {
currentItem.setLink(new String(ch, start, length));
parsingLink = false;
}
}
}
}
RssReader.java
public class RssParseHandler extends DefaultHandler {
private List<RssItem> rssItems;
// Used to reference item while parsing
private RssItem currentItem;
// Parsing title indicator
private boolean parsingTitle;
// A buffer used to build current title being parsed
private StringBuffer currentTitleSb;
// Parsing pubDate indicator
private boolean parsingpubDate;
// A buffer used to build current pubDate being parsed
private StringBuffer currentpubDateSb;
// Parsing description indicator
private boolean parsingDescription;
// A buffer used to build current description being parsed
private StringBuffer currentDescriptionSb;
// Parsing link indicator
private boolean parsingLink;
public RssParseHandler() {
rssItems = new ArrayList<RssItem>();
}
public List<RssItem> getItems() {
return rssItems;
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("item".equals(qName)) {
currentItem = new RssItem(0, qName, qName, qName);
} else if ("title".equals(qName)) {
parsingTitle = true;
currentTitleSb = new StringBuffer();
}
else if ("pubDate".equals(qName)) {
parsingpubDate = true;
currentpubDateSb = new StringBuffer();
}
else if ("description".equals(qName)) {
parsingDescription = true;
currentDescriptionSb = new StringBuffer();
}
else if ("link".equals(qName)) {
parsingLink = true;
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("item".equals(qName)) {
rssItems.add(currentItem);
currentItem = null;
}
else if ("title".equals(qName)) {
parsingTitle = false;
// Set item's title when we parse item->title tag not the channel title tag
if (currentItem != null) {
// Set item's title here
currentItem.setTitle(currentTitleSb.toString());
}
}
else if ("pubDate".equals(qName)) {
parsingpubDate = false;
// Set item's pubDate when we parse item->pubDate tag not the channel pubDate tag
if (currentItem != null) {
// Set item's pubDate here
currentItem.setpubDate(currentpubDateSb.toString());
}
}
else if ("description".equals(qName)) {
parsingDescription = false;
// Set item's description when we parse item->description tag not the channel description tag
if (currentItem != null) {
// Set item's description here
currentItem.setDescription(currentDescriptionSb.toString());
}
}
else if ("link".equals(qName)) {
parsingLink = false;
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (parsingTitle) {
if (currentItem != null) {
// Here we append the title to the buffer due to network issues.
// Sometimes this characters method is called multiple times for a tag contents.
currentTitleSb.append(new String(ch, start, length));
}
}
if (parsingpubDate) {
if (currentItem != null) {
// Here we append the pubDate to the buffer due to network issues.
// Sometimes this characters method is called multiple times for a tag contents.
currentpubDateSb.append(new String(ch, start, length));
}
}
if (parsingDescription) {
if (currentItem != null) {
// Here we append the description to the buffer due to network issues.
// Sometimes this characters method is called multiple times for a tag contents.
currentDescriptionSb.append(new String(ch, start, length));
}
}
else if (parsingLink) {
if (currentItem != null) {
currentItem.setLink(new String(ch, start, length));
parsingLink = false;
}
}
}
}
RssItem.java
public class RssItem {
public int imageId;
// item title
public String title;
// item link
public String link;
// item pubDate
public String pubDate;
// item description
public String description;
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
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 getpubDate() {
return pubDate;
}
public void setpubDate(String pubDate) {
this.pubDate = pubDate;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public RssItem(int imageId, String title, String description, String link) {
this.imageId = imageId;
this.title = title;
this.description = description;
this.link = link;
}
#Override
public String toString() {
return title + "\n" + description + "\n" + pubDate;
}
}

Use Below url
http://iamvijayakumar.blogspot.in/2012/06/android-rss-feed-reader-example.html
RSS Parser with CustomAdapter using AsyncTask

Related

How do I use AsyncTask on a parser? [duplicate]

This question already has an answer here:
java.lang.StackOverflowError trying to parse in a AsyncTask
(1 answer)
Closed 8 years ago.
I have been reading this tutorial and came across the problem that it uses a very low api. I got the NetworkOnMainThreadException. I found this answer on stackoverflow which says I have to use AsyncTask.
I have tried using AsyncTask on an empty project working with another tutorial which worked fine.
My problem is that I need to change this project so that I can use it on higher apis. So the thing is AndroidSaxFeedParser is a subclass and AsyncTask is a super class and the error line is on AndroidSaxFeedParser which extends BaseFeedParser and BaseFeedParser extends FeedParser which is an interface(btw I always thought interfaces had to be implemented instead of extended?).
To be more precise the errors are on these line(indicated with --->) :
AndroidSaxFeedParser.java :
try
{
---> Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
}
catch (Exception e)
{
---> throw new RuntimeException(e);
}
MessageList.java :
private void loadFeed(ParserType type)
{
try
{
Log.i("AndroidNews", "ParserType=" + type.name());
FeedParser parser = FeedParserFactory.getParser(type);
long start = System.currentTimeMillis();
---> messages = parser.parse();
long duration = System.currentTimeMillis() - start;
Log.i("AndroidNews", "Parser duration=" + duration);
String xml = writeXml();
Log.i("AndroidNews", xml);
List<String> titles = new ArrayList<String>(messages.size());
for (Message msg : messages)
{
titles.add(msg.getTitle());
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.row, titles);
this.setListAdapter(adapter);
}
catch (Throwable t)
{
Log.e("AndroidNews", t.getMessage(), t);
}
}
BaseFeedParser.java :
protected InputStream getInputStream()
{
try
{
---> return feedUrl.openConnection().getInputStream();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
So where and how should I use the AsyncTask. (I'm only using the AndroidSaxParser so the other parsers in the tutorial can be ignored).
AndroidSaxFeedParser.java
public class AndroidSaxFeedParser extends BaseFeedParser
{
static final String RSS = "rss";
public AndroidSaxFeedParser(String feedUrl)
{
super(feedUrl);
}
public List<Message> parse()
{
final Message currentMessage = new Message();
RootElement root = new RootElement(RSS);
final List<Message> messages = new ArrayList<Message>();
Element channel = root.getChild(CHANNEL);
Element item = channel.getChild(ITEM);
item.setEndElementListener(new EndElementListener()
{
public void end()
{
messages.add(currentMessage.copy());
}
});
item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener()
{
public void end(String body)
{
currentMessage.setTitle(body);
}
});
item.getChild(LINK).setEndTextElementListener(new EndTextElementListener()
{
public void end(String body)
{
currentMessage.setLink(body);
}
});
item.getChild(DESCRIPTION).setEndTextElementListener(new EndTextElementListener()
{
public void end(String body)
{
currentMessage.setDescription(body);
}
});
item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener()
{
public void end(String body)
{
currentMessage.setDate(body);
}
});
try
{
Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
}
catch (Exception e)
{
throw new RuntimeException(e);
}
return messages;
}
}
BaseFeedParser.java
public abstract class BaseFeedParser implements FeedParser
{
// names of the XML tags
static final String CHANNEL = "channel";
static final String PUB_DATE = "pubDate";
static final String DESCRIPTION = "description";
static final String LINK = "link";
static final String TITLE = "title";
static final String ITEM = "item";
private final URL feedUrl;
protected BaseFeedParser(String feedUrl)
{
try
{
this.feedUrl = new URL(feedUrl);
}
catch (MalformedURLException e)
{
throw new RuntimeException(e);
}
}
protected InputStream getInputStream()
{
try
{
return feedUrl.openConnection().getInputStream();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
}
FeedParser.java
public interface FeedParser
{
List<Message> parse();
}
FeedParserFactory.java
public abstract class FeedParserFactory
{
static String feedUrl = "http://example.com/feed/";
public static FeedParser getParser()
{
return getParser(ParserType.ANDROID_SAX);
}
public static FeedParser getParser(ParserType type)
{
switch (type)
{
case SAX:
return new SaxFeedParser(feedUrl);
case DOM:
return new DomFeedParser(feedUrl);
case ANDROID_SAX:
return new AndroidSaxFeedParser(feedUrl);
case XML_PULL:
return new XmlPullFeedParser(feedUrl);
default:
return null;
}
}
}
Message.java
public class Message implements Comparable<Message>
{
static SimpleDateFormat FORMATTER = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss Z", Locale.ENGLISH);
private String title;
private URL link;
private String description;
private Date date;
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title.trim();
}
// getters and setters omitted for brevity
public URL getLink()
{
return link;
}
public void setLink(String link)
{
try
{
this.link = new URL(link);
}
catch (MalformedURLException e)
{
throw new RuntimeException(e);
}
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description.trim();
}
public String getDate()
{
return FORMATTER.format(this.date);
}
public void setDate(String date)
{
// pad the date if necessary
while (!date.endsWith("00"))
{
date += "0";
}
try
{
this.date = FORMATTER.parse(date.trim());
}
catch (ParseException e)
{
throw new RuntimeException(e);
}
}
public Message copy()
{
Message copy = new Message();
copy.title = title;
copy.link = link;
copy.description = description;
copy.date = date;
return copy;
}
#Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("Title: ");
sb.append(title);
sb.append('\n');
sb.append("Date: ");
sb.append(this.getDate());
sb.append('\n');
sb.append("Link: ");
sb.append(link);
sb.append('\n');
sb.append("Description: ");
sb.append(description);
return sb.toString();
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((date == null) ? 0 : date.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((link == null) ? 0 : link.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Message other = (Message) obj;
if (date == null)
{
if (other.date != null)
return false;
}
else if (!date.equals(other.date))
return false;
if (description == null)
{
if (other.description != null)
return false;
}
else if (!description.equals(other.description))
return false;
if (link == null)
{
if (other.link != null)
return false;
}
else if (!link.equals(other.link))
return false;
if (title == null)
{
if (other.title != null)
return false;
}
else if (!title.equals(other.title))
return false;
return true;
}
public int compareTo(Message another)
{
if (another == null)
return 1;
// sort descending, most recent first
return another.date.compareTo(date);
}
}
MessageList.java
public class MessageList extends ListActivity
{
private List<Message> messages;
#Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.main);
loadFeed(ParserType.ANDROID_SAX);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
menu.add(Menu.NONE, ParserType.ANDROID_SAX.ordinal(), ParserType.ANDROID_SAX.ordinal(), R.string.android_sax);
menu.add(Menu.NONE, ParserType.SAX.ordinal(), ParserType.SAX.ordinal(), R.string.sax);
menu.add(Menu.NONE, ParserType.DOM.ordinal(), ParserType.DOM.ordinal(), R.string.dom);
menu.add(Menu.NONE, ParserType.XML_PULL.ordinal(), ParserType.XML_PULL.ordinal(), R.string.pull);
return true;
}
#SuppressWarnings("unchecked")
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item)
{
super.onMenuItemSelected(featureId, item);
ParserType type = ParserType.values()[item.getItemId()];
ArrayAdapter<String> adapter = (ArrayAdapter<String>) this.getListAdapter();
if (adapter.getCount() > 0)
{
adapter.clear();
}
this.loadFeed(type);
return true;
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
Intent viewMessage = new Intent(Intent.ACTION_VIEW, Uri.parse(messages.get(position).getLink().toExternalForm()));
this.startActivity(viewMessage);
}
private void loadFeed(ParserType type)
{
try
{
Log.i("AndroidNews", "ParserType=" + type.name());
FeedParser parser = FeedParserFactory.getParser(type);
long start = System.currentTimeMillis();
messages = parser.parse();
long duration = System.currentTimeMillis() - start;
Log.i("AndroidNews", "Parser duration=" + duration);
String xml = writeXml();
Log.i("AndroidNews", xml);
List<String> titles = new ArrayList<String>(messages.size());
for (Message msg : messages)
{
titles.add(msg.getTitle());
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.row, titles);
this.setListAdapter(adapter);
}
catch (Throwable t)
{
Log.e("AndroidNews", t.getMessage(), t);
}
}
private String writeXml()
{
XmlSerializer serializer = Xml.newSerializer();
StringWriter writer = new StringWriter();
try
{
serializer.setOutput(writer);
serializer.startDocument("UTF-8", true);
serializer.startTag("", "messages");
serializer.attribute("", "number", String.valueOf(messages.size()));
for (Message msg : messages)
{
serializer.startTag("", "message");
serializer.attribute("", "date", msg.getDate());
serializer.startTag("", "title");
serializer.text(msg.getTitle());
serializer.endTag("", "title");
serializer.startTag("", "url");
serializer.text(msg.getLink().toExternalForm());
serializer.endTag("", "url");
serializer.startTag("", "body");
serializer.text(msg.getDescription());
serializer.endTag("", "body");
serializer.endTag("", "message");
}
serializer.endTag("", "messages");
serializer.endDocument();
return writer.toString();
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
ParserType.java
public enum ParserType
{
SAX, DOM, ANDROID_SAX, XML_PULL;
}
RssHandler.java
public class RssHandler extends DefaultHandler
{
private List<Message> messages;
private Message currentMessage;
private StringBuilder builder;
public List<Message> getMessages()
{
return this.messages;
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException
{
super.characters(ch, start, length);
builder.append(ch, start, length);
}
#Override
public void endElement(String uri, String localName, String name) throws SAXException
{
super.endElement(uri, localName, name);
if (this.currentMessage != null)
{
if (localName.equalsIgnoreCase(TITLE))
{
currentMessage.setTitle(builder.toString());
}
else if (localName.equalsIgnoreCase(LINK))
{
currentMessage.setLink(builder.toString());
}
else if (localName.equalsIgnoreCase(DESCRIPTION))
{
currentMessage.setDescription(builder.toString());
}
else if (localName.equalsIgnoreCase(PUB_DATE))
{
currentMessage.setDate(builder.toString());
}
else if (localName.equalsIgnoreCase(ITEM))
{
messages.add(currentMessage);
}
builder.setLength(0);
}
}
#Override
public void startDocument() throws SAXException
{
super.startDocument();
messages = new ArrayList<Message>();
builder = new StringBuilder();
}
#Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException
{
super.startElement(uri, localName, name, attributes);
if (localName.equalsIgnoreCase(ITEM))
{
this.currentMessage = new Message();
}
}
}
public class ParseAsync extends AsyncTask<Url, Void, ArrayList<FeedItem>> {
#Override
protected ArrayList<FeedItem> doInBackground(Url... params) {
//url as parametr, long time operation
return YourParser.parseFeed(params[0])
}
#Override
protected void onPostExecute(ArrayList<FeedItem> result) {
// this we get result of parser in ui thread
}
}
In ui thread
ParseAsync task = new ParseAsync();
task.execute("www.example.ru/feed.rss")
Answer
I fixed my problem if anyone is interested you can read that question.
i think the problem is because of NetworkOnMainThreadException,So what you want to do is that you need to add StrictMode
Where you use the Async task,so just add this linke on preexectue of the async task
int SDK_INT = android.os.Build.VERSION.SDK_INT;
if (SDK_INT>8){
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
Hope this will solve your problem

ListView displaying incorrect title

I have a simple application that pulls an XML file from pc worlds RSS feed here:
http://feeds.pcworld.com/pcworld/latestnews
I want to display the name of the titles in a ListView then when the user selects one the article opens up in a browser window.
The application is working the only thing is that the title is not being displayed correctly in the ListView.
It should be something like this:
Make you website stand out with Windows 8
But instead it is this:
com.example.simplerss.Item#424b9998
Any ideas?
This is my code for the MainActivity
public class MainActivity extends ListActivity {
ArrayAdapter<Item> adapter;
List<Item>items;//Holds item objects containing info relating to element pulled from XML file.
Item item;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initialize variables
items = new ArrayList<Item>();
new PostTask().execute();
adapter= new ArrayAdapter<Item>(this, android.R.layout.simple_list_item_1, items);
setListAdapter(adapter);
}
private InputStream getInputStream(URL url) {
try{
return url.openConnection().getInputStream();
}catch(IOException e){
return null;
}
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Uri uri = items.get(position).getLink();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
//ASYNC CLASS
private class PostTask extends AsyncTask<String, Integer, String>{
#Override
protected String doInBackground(String... arg0) {
try{
//link to data source
URL url = new URL("http://feeds.pcworld.com/pcworld/latestnews");
//Set up parser
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser xpp = factory.newPullParser();
//get XML from input stream
InputStream in = getInputStream(url);
if (in == null) {
throw new Exception("Empty inputstream");
}
xpp.setInput(in, "UTF_8");
//Keep track of which tag inside of XML
boolean insideItem = false;
//Loop through the XML file and extract data required
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
Log.v("ENTER", String.valueOf(xpp.getEventType()));
if (xpp.getName().equalsIgnoreCase("item")) {
insideItem = true;
//Create new item object
item = new Item();
} else if (xpp.getName().equalsIgnoreCase("title")) {
if (insideItem){
item.setTitle(xpp.nextText());
Log.i("title", item.getTitle());
}
}
else if (xpp.getName().equalsIgnoreCase("description")) {
if (insideItem){
item.setDescription(xpp.nextText());
}
}
else if (xpp.getName().equalsIgnoreCase("link")) {
if (insideItem){
item.setLink(Uri.parse(xpp.nextText()));
}
}
}else if(eventType==XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){
insideItem=false;
//add item to list
items.add(item);
}
eventType = xpp.next(); //move to next element
publishProgress();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
return "COMPLETED";
}
#Override
protected void onProgressUpdate(Integer... values) {
adapter.notifyDataSetChanged();
}
public void onPostExecute(String s) {
Toast.makeText(getApplicationContext(), s + " Items: " + items.size(), Toast.LENGTH_SHORT).show();
adapter.notifyDataSetChanged();
}
}
}
and for the Item Class
public class Item {
//Variables
private String title;
private Uri link;
private String description;
public Item() {
super();
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Uri getLink() {
return link;
}
public void setLink(Uri link) {
this.link = link;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Override the toString() method in Item.
#Override
public String toString() {
return title;
}
This should solve your problem.
Right now, the ArrayAdapter sets its View's texts to Item.toString(), but this is the default method of Object that returns the Object's ID. With overriding it, you give it a meaningful value, in your case the title.
I think the problem lies in:
else if (xpp.getName().equalsIgnoreCase("title")) {
if (insideItem){
item.setTitle(xpp.nextText());
Log.i("title", item.getTitle());
}
}
Here, getName() is a method from the Java Class object. The method you want is readContent() I think. I haven't used this library so that may not be exactly correct but you can certainly find what you need in the docs.

Android RSS parsing too slow - doing something wrong?

I followed a tutorial on how to parse XML(RSS) files on an Android app. Below is my code that is working, but is taking quite long. Am I doing something incorrect or in a way that would slow it down? It takes 7-10 seconds to load 30-35 articles... seemingly way too long, and certainly too long for a user to wait every time they switch sections (which pulls in another feed)
I do have things in place to only pull new data every hour...etc ... but the first time still takes 10 seconds usually, which - by then, the user thinks their app has crashed...etc.
I am doing this in an AsyncTask
I'm not downloading the images at this point
This IS the slow part of the code (not internet, or displaying... etc)
TLDR:
This code is too slow - why?:
package com.mysite.utilities;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
public class RSSHandler extends DefaultHandler
{
// creats a news item class to hold data within loop
public class NewsItem
{
public String title;
public String subhead;
public String link;
public String byline;
public String description;
public String storytext;
public String cmsstoryid;
public String pubDate;
public String keyword;
public String category;
public String subcategory;
public String slotreference;
public String lastModTime;
public ArrayList<PhotoItem> photos = new ArrayList<PhotoItem>();
#Override
public String toString()
{
return title;
}
}
//creates a photo item class to hold image data within loop
public class PhotoItem
{
public String photoid; //tribs id
public String caption;
public String height;
public String width;
public String photo; //full path to photo
public String thumbnail; //full path to thumbnail
public int articleid;
public String photolastmodified;
#Override
public String toString()
{
return photo;
}
}
//creates instances of classes to be used in loop
private StringBuffer buf; //to hold element characters with loop
private ArrayList<NewsItem> feedItems;
private NewsItem item;
private PhotoItem photoitem;
//initialize variables of whether or not it's within an item (or photo item)
private boolean inItem = false;
private boolean inPhotoItem = false;
//
public ArrayList<NewsItem> getParsedItems() {
return feedItems;
}
//Called at the head of each new element
#Override
public void startElement(String uri, String name, String qName, Attributes atts)
{
//creates an array of news items
if ("channel".equals(name))
{
feedItems = new ArrayList<NewsItem>();
}
//creates a news item and toggles "in news item" to on
else if ("item".equals(name))
{
item = new NewsItem();
inItem = true;
}
//creates a photo item and toggles "in photo item" to on
else if ("image".equals(name))
{
photoitem = new PhotoItem();
inPhotoItem = true;
}
//starts a new string buffer if matches an elemnt we want from news item
else if (
("title".equals(name) ||
"subhead".equals(name) ||
"link".equals(name) ||
"byline".equals(name) ||
"description".equals(name) ||
"storytext".equals(name) ||
"keyword".equals(name) ||
"cmsstoryid".equals(name) ||
"pubDate".equals(name) ||
"category".equals(name) ||
"subcategory".equals(name) ||
"lastModTime".equals(name) ||
"slotreference".equals(name)
)
&& inItem)
{
buf = new StringBuffer();
}
//starts an a new string buffer if it matches an element we want from image item
else if(
("caption".equals(name) ||
"photoid".equals(name) ||
"height".equals(name) ||
"width".equals(name) ||
"photo".equals(name) ||
"photolastmodified".equals(name) ||
"thumbnail".equals(name)
)
&& inPhotoItem)
{
buf = new StringBuffer();
}
}
//Called at the tail of each element end
#Override
public void endElement(String uri, String name, String qName)
{
if ("item".equals(name))
{
feedItems.add(item);
inItem = false;
}
else if ("image".equals(name))
{
try {
item.photos.add(photoitem);
} catch (Exception e) {
System.out.println(e);
}
inPhotoItem = false;
}
else if (inItem)
{
if (inPhotoItem)
{
if ("caption".equals(name)) { photoitem.caption = buf.toString(); }
else if ("photoid".equals(name)) { photoitem.photoid = buf.toString(); }
else if ("height".equals(name)) { photoitem.height = buf.toString(); }
else if ("width".equals(name)) { photoitem.width = buf.toString(); }
else if ("photo".equals(name)) { photoitem.photo = buf.toString(); }
else if ("photolastmodified".equals(name)) { photoitem.photolastmodified = buf.toString(); }
else if ("thumbnail".equals(name)) { photoitem.thumbnail = buf.toString(); }
}
else if ("title".equals(name)) { item.title = buf.toString(); }
else if ("subhead".equals(name)) { item.subhead = buf.toString(); }
else if ("link".equals(name)) { item.link = buf.toString(); }
else if ("byline".equals(name)) { item.byline = buf.toString(); }
else if ("description".equals(name)) { item.description = buf.toString(); }
else if ("storytext".equals(name)) { item.storytext = buf.toString(); }
else if ("keyword".equals(name)) { item.keyword = buf.toString(); }
else if ("cmsstoryid".equals(name)) { item.cmsstoryid = buf.toString(); }
else if ("pubDate".equals(name)) { item.pubDate = buf.toString(); }
else if ("category".equals(name)) { item.category = buf.toString(); }
else if ("subcategory".equals(name)) { item.subcategory = buf.toString(); }
else if ("lastModTime".equals(name)) { item.lastModTime = buf.toString(); }
else if ("slotreference".equals(name)) { item.slotreference = buf.toString(); }
}
else
{
buf = null;
}
}
//Called with character data inside elements
#Override
public void characters(char ch[], int start, int length)
{
//Don't bother if buffer isn't initialized
if(buf != null)
{
for (int i=start; i<start+length; i++)
{
buf.append(ch[i]);
}
}
}
}
My updated code thus far (still no speed increase):
package com.sltrib.utilities;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
public class RSSHandler extends DefaultHandler
{
// creats a news item class to hold data within loop
public class NewsItem
{
public String title;
public String subhead;
public String link;
public String byline;
public String description;
public String storytext;
public String cmsstoryid;
public String pubDate;
public String keyword;
public String category;
public String subcategory;
public String slotreference;
public String lastModTime;
public ArrayList<PhotoItem> photos = new ArrayList<PhotoItem>();
#Override
public String toString()
{
return title;
}
}
//creates a photo item class to hold image data within loop
public class PhotoItem
{
public String photoid; //tribs id
public String caption;
public String height;
public String width;
public String photo; //full path to photo
public String thumbnail; //full path to thumbnail
public int articleid;
public String photolastmodified;
#Override
public String toString()
{
return photo;
}
}
//creates instances of classes to be used in loop
private StringBuilder buf; //to hold element characters with loop
private ArrayList<NewsItem> feedItems;
private NewsItem item;
private PhotoItem photoitem;
//initialize variables of whether or not it's within an item (or photo item)
private boolean inItem = false;
private int currentTagId = 0;
//
public ArrayList<NewsItem> getParsedItems() {
return feedItems;
}
#Override
public void startDocument()
{
feedItems = new ArrayList<NewsItem>(); //creates an array to hold feed items
}
//Called at the head of each new element
#Override
public void startElement(String uri, String name, String qName, Attributes atts)
{
//gets the id of the current tag
currentTagId = 0;
String tmpId = atts.getValue("id");
if(tmpId != null)
{
currentTagId = Integer.parseInt(tmpId);
}
//creates a news item
if (currentTagId == 99) // <item>
{
item = new NewsItem();
inItem = true;
}
//creates a photo item
else if (currentTagId == 21) { // <image>
photoitem = new PhotoItem();
}
//creates a string builder if it's a tag within an article or a photo
else if (inItem && currentTagId > 0 && currentTagId < 29)
{
buf = new StringBuilder();
}
}
//Called at the tail of each element end
#Override
public void endElement(String uri, String name, String qName)
{
// it's not getting the tag id - how?
Log.d("XML", "endElement:" + Integer.toString(currentTagId));
if (currentTagId == 99) // </item>
{
Log.d("XML", "Should be adding item: " + item.title);
feedItems.add(item);
inItem=false;
}
else if (currentTagId == 21) // </image>
{
try {
item.photos.add(photoitem);
} catch (Exception e) {
System.out.println(e);
}
}
else
{
switch(currentTagId)
{
case 1: item.title = buf.toString(); break;
case 2: item.subhead = buf.toString(); break;
case 3: item.link = buf.toString(); break;
case 4: item.byline = buf.toString(); break;
case 5: item.description = buf.toString(); break;
case 6: item.storytext = buf.toString(); break;
case 11: item.cmsstoryid = buf.toString(); break;
case 14: item.pubDate = buf.toString(); break;
case 15: item.lastModTime = buf.toString(); break;
case 16: item.keyword = buf.toString(); break;
case 17: item.category = buf.toString(); break;
case 18: item.subcategory = buf.toString(); break;
case 19: item.slotreference = buf.toString(); break;
case 22: photoitem.caption = buf.toString(); break;
case 23: photoitem.photoid = buf.toString(); break;
case 24: photoitem.photolastmodified = buf.toString(); break;
case 25: photoitem.height = buf.toString(); break;
case 26: photoitem.width = buf.toString(); break;
case 27: photoitem.photo = buf.toString(); break;
case 28: photoitem.thumbnail = buf.toString(); break;
default: if(!inItem) buf = null;
}
}
}
//Called with character data inside elements
#Override
public void characters(char ch[], int start, int length)
{
if(buf != null)
{
String chars = new String(ch, start, length); // get all text value inside the element tag
chars = chars.trim(); // remove all white-space characters
buf.append(chars);
}
}
}
Perhaps you are already doing this, but I just wanted to reiterate that this should be done on another thread. The user wont think the app has crashed if you display a progress indicator (spinner) and keep the GUI responsive.
If you are not doing this on a background thread, it could be making this artificially slow because the system is fighting to keep the user interface going.
As to why this is slow, there is a TON of branching. The more if statements you have, and the more elses (etc) you have, the more difficult it is for the branch predictor do do its job.
Also, I can't tell if you are downloading the images here, but if you are, that should be done asynchronously after the text data is retrieved and displayed to the user (to make the user interface more responsive).

SAX parsing issue

how can I parse XML like this
<rss version="0.92">
<channel>
<title>MyTitle</title>
<link>http://myurl.com</link>
<description>MyDescription</description>
<lastBuildDate>SomeDate</lastBuildDate>
<docs>http://someurl.com</docs>
<language>SomeLanguage</language>
<item>
<title>TitleOne</title>
<description><![CDATA[Some text.]]></description>
<link>http://linktoarticle.com</link>
</item>
<item>
<title>TitleTwo</title>
<description><![CDATA[Some other text.]]></description>
<link>http://linktoanotherarticle.com</link>
</item>
</channel>
</rss>
please any one help.
try this
public class ExampleHandler extends DefaultHandler {
private Channel channel;
private Items items;
private Item item;
private boolean inItem = false;
private StringBuilder content;
public ExampleHandler() {
items = new Items();
content = new StringBuilder();
}
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
content = new StringBuilder();
if(localName.equalsIgnoreCase("channel")) {
channel = new Channel();
} else if(localName.equalsIgnoreCase("item")) {
inItem = true;
item = new Item();
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(localName.equalsIgnoreCase("title")) {
if(inItem) {
item.setTitle(content.toString());
} else {
channel.setTitle(content.toString());
}
} else if(localName.equalsIgnoreCase("link")) {
if(inItem) {
item.setLink(content.toString());
} else {
channel.setLink(content.toString());
}
} else if(localName.equalsIgnoreCase("description")) {
if(inItem) {
item.setDescription(content.toString());
} else {
channel.setDescription(content.toString());
}
} else if(localName.equalsIgnoreCase("lastBuildDate")) {
channel.setLastBuildDate(content.toString());
} else if(localName.equalsIgnoreCase("docs")) {
channel.setDocs(content.toString());
} else if(localName.equalsIgnoreCase("language")) {
channel.setLanguage(content.toString());
} else if(localName.equalsIgnoreCase("item")) {
inItem = false;
items.add(item);
} else if(localName.equalsIgnoreCase("channel")) {
channel.setItems(items);
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
content.append(ch, start, length);
}
public void endDocument() throws SAXException {
// you can do something here for example send
// the Channel object somewhere or whatever.
}
}
where Item,Items and Channel are getter setter class ...
to know more visit this question How to parse XML using the SAX parser

Parse xml data into hashtable and displaying in listview?

I have a problem. I have multiple records that after SAX parsing from a xml file that needs to be inserted into the Hashtable and displayed in a listview. I am able to display the data in the listview but all it gives is the same data for all rows in the listview. I think it has something to do with either my coding for the hashtable or my SAX parsing.
This is the xml file I'm trying to retrieve data from online: http://spark.opac.tp.edu.sg/X?op=present&set_no=007584&set_entry=000000001,000000002,000000003,000000004,000000005&format=marc
Below is my handler where i place my data into the hashtable:
ArrayList<Hashtable<String,String>> list = new ArrayList<Hashtable<String,String>>();
Hashtable<String,String> data = new Hashtable<String,String>();
private final String MY_DEBUG_TAG = "Debugging~";
private Boolean in_record = false;
private Boolean in_author = false;
private Boolean in_format = false;
private Boolean in_title = false;
private Boolean in_callNumber = false;
private String format = "";
private String title = "";
private String author = "";
private String callNumber = "";
//private SearchList sList;
//public SearchList getListData() {
// return this.sList;
//}
#Override
public void startDocument() throws SAXException {
// this.sList = new SearchList();
}
#Override
public void endDocument() throws SAXException {
// Nothing to do
}
/** Called when tag starts ( ex:- <name>AndroidPeople</name>
* -- <name> )*/
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(localName.equalsIgnoreCase("record")) {
this.in_record = true;
}
else
if (localName.equalsIgnoreCase("fixfield")) {
if (attributes.getValue("id").equalsIgnoreCase("FMT")) {
this.in_format = true;
}
}
else
if(localName.equalsIgnoreCase("varfield")) {
if(attributes.getValue("id").equalsIgnoreCase("100")) {
this.in_author = true;
}
else
if(attributes.getValue("id").equalsIgnoreCase("245")) {
this.in_title = true;
}
else
if(attributes.getValue("id").equalsIgnoreCase("099")) {
this.in_callNumber = true;
}
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
StringBuffer sb = new StringBuffer();
String finalString;
String originalString = "";
String chars = new String(ch, start, length);
chars = chars.trim();
if (this.in_format) {
sb.append(chars);
finalString = sb.toString();
this.format = finalString;
}
else
if (this.in_author) {
if(!(chars.equals(""))) {
sb.append(chars);
finalString = sb.toString();
originalString = this.author + finalString;
this.author = originalString;
}
}
else
if (this.in_title) {
if(!(chars.equals(""))) {
sb.append(chars);
finalString = sb.toString();
originalString = this.title + finalString;
this.title = originalString;
}
}
else
if (this.in_callNumber) {
if(!(chars.equals(""))) {
sb.append(chars);
finalString = sb.toString();
this.callNumber = finalString;
}
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (localName.equalsIgnoreCase("record")) {
this.in_record=false;
}
else
if (localName.equalsIgnoreCase("fixfield")) {
if (this.in_format) {
//set the foundCharacter to Hashtable
data.put("format", this.format);
//sList.setFormat(this.format);
Log.d(MY_DEBUG_TAG,"Format = " + this.format);
this.in_format = false;
}
}
else
if(localName.equalsIgnoreCase("varfield")) {
if (this.in_author) {
//set the foundCharacter to Hashtable
data.put("author", this.author);
//sList.setAuthor(this.author);
Log.d(MY_DEBUG_TAG,"Author = " + this.author);
this.in_author = false;
}
else
if (this.in_title) {
//set the foundCharacter to Hashtable
data.put("title", this.title);
//sList.setTitle(this.title);
Log.d(MY_DEBUG_TAG,"Title = " + this.title);
this.in_title = false;
}
else
if (this.in_callNumber) {
//set the foundCharacter to Hashtable
data.put("callNumber", this.callNumber);
//sList.setCallNumber(this.callNumber);
Log.d(MY_DEBUG_TAG,"Call Number = " + this.callNumber);
this.in_callNumber = false;
}
}
//add the hashtable into ArrayList
list.add(data);
}
Any suggestions guys?
I don't have time to read completly your code ...
But this is a simple example :
ListView myListView;
myListView = (ListView) findViewById(R.id.mylistview);
ArrayList<HashMap<String, String>> listItem = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map;
//load your data
String[][] items = database.getItems("Blog");
//check if the database was empty
if(items != null){
for(int i = 0; i < items[0].length; i++) {
map = new HashMap<String, String>();
map.put("pubdate", items[2][0]);
map.put("title", items[0][i]);
map.put("description", items[1][i]);
listItem.add(map);
}
//Creation of a SimpleAdapter to put items in your list (listitems) in your listview
// You need to have a xml file called list_full_news_item with elements
// called android:id="#+id/title" etc.
SimpleAdapter mSimpleAdaptor = new SimpleAdapter (this.getBaseContext(), listItem, R.layout.list_full_news_item,
new String[] {"pubdate", "title", "description"}, new int[] {R.id.itemPubdate, R.id.itemTitle, R.id.itemDescription});
//Assign to the listView the created adapter
myListView.setAdapter(mSimpleAdaptor);
}
Hope this will help you to understand.
You should not use the SAX Parser and use the Simple XML Library instead. It has the #ElementMap annotation for exactly this purpose. This turns your entire problem into one annotation and three lines of code to read the XML in. Look at my blog post on including the library in an android project and look at the Simple tutorial if you want to see how to use all of its cool features.
Edit: I just realised that I have answered this question before in one of your previous questions. I'm done trying to convince you to look into Simple XML; but please, stop posting essentially the exact same question in five different ways here; people have helped you already, give you answers and lead you in the right direction. It is now time to read more, experiment and learn.

Categories

Resources