我正在为学校报纸创建一个应用程序,并在尝试显示完整文章时遇到问题。目前,我有一个从RSS源中提取的文章列表,当点击一个文章时,它会显示文章的内容。但是只有第一段显示在TextView中,无论它有多长。这让我觉得它与<p></p>
HTML标记有关。我不熟悉RSS提要或解析XML(这是我第一次尝试它)并且已经四处寻找方法去做我想要完成的事情。
来自:Android TextView cuts off after one paragraph
我是根据上述问题的结果创建此问题的。我认为我的应用程序的问题与TextView及其属性有关,但通过使用我在其中硬编码的纯文本操作得很好。
根据我尝试的评论和事情,问题似乎是应用程序如何从RSS源中读取信息。就像我之前说的那样,这是我第一次在Android中使用RSS提要,而我正在使用示例项目代码(可以在之前的问题中找到)。以下是与RSS提要相关的代码:
的RSSFeed 的.java:
public class RSSFeed {
private String title = null;
private String description = null;
private String link = null;
private String pubdate = null;
private String content = null;
private List<RSSItem> itemList;
RSSFeed(){
itemList = new Vector<RSSItem>(0);
}
void addItem(RSSItem item){
itemList.add(item);
}
RSSItem getItem(int location){
return itemList.get(location);
}
List<RSSItem> getList(){
return itemList;
}
void setTitle(String value){
title = value;
}
void setDescription(String value){
description = value;
}
void setLink(String value){
link = value;
}
void setPubdate(String value){
pubdate = value;
}
public void setContent(String value) {
content=value;
}
String getTitle(){
return title;
}
String getDescription(){
return description;
}
String getLink(){
return link;
}
String getPubdate(){
return pubdate;
}
String getContent() {
return content;
}
}
RSSHandler 的.java:
public class RSSHandler extends DefaultHandler {
// Feed and Article objects to use for temporary storage
private Article currentArticle = new Article();
private List<Article> articleList = new ArrayList<Article>();
// Number of articles added so far
private int articlesAdded = 0;
// Number of articles to download
private static final int ARTICLES_LIMIT = 15;
//Current characters being accumulated
StringBuffer chars = new StringBuffer();
/*
* This method is called every time a start element is found (an opening XML marker)
* here we always reset the characters StringBuffer as we are only currently interested
* in the the text values stored at leaf nodes
*
* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
public void startElement(String uri, String localName, String qName, Attributes atts) {
chars = new StringBuffer();
}
/*
* This method is called every time an end element is found (a closing XML marker)
* here we check what element is being closed, if it is a relevant leaf node that we are
* checking, such as Title, then we get the characters we have accumulated in the StringBuffer
* and set the current Article's title to the value
*
* If this is closing the "Item", it means it is the end of the article, so we add that to the list
* and then reset our Article object for the next one on the stream
*
*
* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
public void endElement(String uri, String localName, String qName) throws SAXException {
if (localName.equalsIgnoreCase("title"))
{
Log.d("LOGGING RSS XML", "Setting article title: " + chars.toString());
currentArticle.setTitle(chars.toString());
}
else if (localName.equalsIgnoreCase("description"))
{
Log.d("LOGGING RSS XML", "Setting article description: " + chars.toString());
currentArticle.setDescription(chars.toString());
}
else if (localName.equalsIgnoreCase("pubDate"))
{
Log.d("LOGGING RSS XML", "Setting article published date: " + chars.toString());
currentArticle.setPubDate(chars.toString());
}
else if (localName.equalsIgnoreCase("encoded"))
{
Log.d("LOGGING RSS XML", "Setting article content: " + chars.toString());
currentArticle.setEncodedContent(chars.toString());
}
else if (localName.equalsIgnoreCase("item"))
{
}
else if (localName.equalsIgnoreCase("link"))
{
try {
Log.d("LOGGING RSS XML", "Setting article link url: " + chars.toString());
currentArticle.setUrl(new URL(chars.toString()));
} catch (MalformedURLException e) {
Log.e("RSA Error", e.getMessage());
}
}
// Check if looking for article, and if article is complete
if (localName.equalsIgnoreCase("item")) {
articleList.add(currentArticle);
currentArticle = new Article();
// Lets check if we've hit our limit on number of articles
articlesAdded++;
if (articlesAdded >= ARTICLES_LIMIT)
{
throw new SAXException();
}
}
}
/*
* This method is called when characters are found in between XML markers, however, there is no
* guarantee that this will be called at the end of the node, or that it will be called only once
* , so we just accumulate these and then deal with them in endElement() to be sure we have all the
* text
*
* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
*/
public void characters(char ch[], int start, int length) {
chars.append(new String(ch, start, length));
}
/**
* This is the entry point to the parser and creates the feed to be parsed
*
* @param feedUrl
* @return
*/
public List<Article> getLatestArticles(String feedUrl) {
URL url = null;
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
url = new URL(feedUrl);
xr.setContentHandler(this);
xr.parse(new InputSource(url.openStream()));
} catch (IOException e) {
Log.e("RSS Handler IO", e.getMessage() + " >> " + e.toString());
} catch (SAXException e) {
Log.e("RSS Handler SAX", e.toString());
} catch (ParserConfigurationException e) {
Log.e("RSS Handler Parser Config", e.toString());
}
return articleList;
}
}
的RSSItem 的.java:
public class RSSItem {
private String title = null;
private String description = null;
private String link = null;
private String pubdate = null;
private String content = null;
RSSItem(){
}
void setTitle(String value){
title = value;
}
void setDescription(String value){
description = value;
}
void setLink(String value){
link = value;
}
void setPubdate(String value){
pubdate = value;
}
public void setContent(String value) {
content=value;
}
String getTitle(){
return title;
}
String getDescription(){
return description;
}
String getLink(){
return link;
}
String getPubdate(){
return pubdate;
}
public String getContent() {
return content;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return title;
}
}
AllStoriesFragment 的.java:
public class AllStoriesFragment extends ListFragment {
/*********************************************************************
* RSS Async Task
*********************************************************************/
public class RssLoadingTask extends AsyncTask<Void, Void, Void> {
@Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
displayRss();
}
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
preReadRss();
}
@Override
protected void onProgressUpdate(Void... values) {
// TODO Auto-generated method stub
//super.onProgressUpdate(values);
}
@Override
protected Void doInBackground(Void... arg0) {
// TODO Auto-generated method stub
readRss();
return null;
}
}
/*********************************************************************
* End RSS Async Task
*********************************************************************/
private RSSFeed myRssFeed = null;
TextView feedTitle;
TextView feedDescription;
/*********************************************************************
* Custom Array Adapter
*********************************************************************/
public class MyCustomAdapter extends ArrayAdapter<RSSItem> {
public MyCustomAdapter(Context context, int textViewResourceId, List<RSSItem> list) {
super(context, textViewResourceId, list);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
//return super.getView(position, convertView, parent);
View row = convertView;
if(row==null){
LayoutInflater inflater=getActivity().getLayoutInflater();
row=inflater.inflate(R.layout.row, parent, false);
}
//Set Item Title
TextView listTitle=(TextView)row.findViewById(R.id.listtitle);
listTitle.setText(myRssFeed.getList().get(position).getTitle());
//Set Item PubDate
TextView listPubdate=(TextView)row.findViewById(R.id.listpubdate);
listPubdate.setText(myRssFeed.getList().get(position).getPubdate());
if (position%2 == 0){
listTitle.setBackgroundColor(0xff101010);
listPubdate.setBackgroundColor(0xff101010);
}
else{
listTitle.setBackgroundColor(0xff080808);
listPubdate.setBackgroundColor(0xff080808);
}
return row;
}
}
/*********************************************************************
* End Custom Array Adapter
*********************************************************************/
/** Called when the fragment is first created. */
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_allstories, null);
Log.d("MainActivity", "AllStoriesFragment started.");
feedTitle = (TextView)v.findViewById(R.id.feedtitle);
feedDescription = (TextView)v.findViewById(R.id.feeddescription);
startReadRss();
return v ;
}
private void startReadRss(){
new RssLoadingTask().execute();
}
private void preReadRss(){
setListAdapter(null);
Toast.makeText(getActivity(), "Reading RSS, Please wait.", Toast.LENGTH_LONG).show();
}
private void readRss(){
try {
URL rssUrl = new URL("http://www.campusslate.com/feed/");
InputSource myInputSource = new InputSource(rssUrl.openStream());
SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
RSSHandler myRSSHandler = new RSSHandler();
XMLReader myXMLReader = mySAXParser.getXMLReader();
myXMLReader.setContentHandler(myRSSHandler);
myXMLReader.parse(myInputSource);
myRssFeed = myRSSHandler.getFeed();
}
catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void displayRss(){
if (myRssFeed!=null){
MyCustomAdapter adapter = new MyCustomAdapter(getActivity(), R.layout.row, myRssFeed.getList());
setListAdapter(adapter);
}
}
public void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
Intent intent = new Intent(getActivity(), ShowDetails.class);
intent.putExtra("keyPubdate", myRssFeed.getItem(position).getPubdate());
intent.putExtra("keyLink", myRssFeed.getItem(position).getLink());
intent.putExtra("keyTitle", myRssFeed.getItem(position).getTitle());
intent.putExtra("keyContent", myRssFeed.getItem(position).getContent());
startActivity(intent);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch(item.getItemId()){
case (0): readRss();
break;
default:
break;
}
return true;
}
}
ShowDetails.java发布在另一个问题中,尽管代码可能与我目前的代码略有不同。现在的问题是列表中的每个项目都是从RSS Feed中读取的最后一项。
如果我有足够的声誉,会发布图片。
答案 0 :(得分:0)
XML元素可能有多个文本节点。您的代码假定只有一个。请在characters()
回调中使用追加操作,而不是设置操作。