Я создаю приложение для своей школьной газеты и сталкиваюсь с проблемой при попытке отобразить полную статью. В настоящее время у меня появляется список статей, которые извлекаются из RSS-канала, и при нажатии на них появляется содержимое статьи. Однако в TextView отображается только первый абзац, независимо от его длины. Это наводит меня на мысль, что это как-то связано с HTML-тегами <p></p>
. Я не так хорошо знаком с RSS-каналами или синтаксическим анализом XML (я впервые пытаюсь это сделать) и искал способы сделать то, что я пытаюсь сделать.
From: Android TextView обрезается после одного абзаца
Я создаю этот вопрос на основе результатов вышеуказанного вопроса. Я думал, что проблема с моим приложением как-то связана с TextView и его свойствами, но с использованием простого текста, который я жестко запрограммировал, он работает нормально.
Судя по комментариям и тому, что я пробовал, проблема заключается в том, как приложение считывает информацию из RSS-канала. Как я уже говорил, я впервые работаю с RSS-каналами в Android, и я использую пример кода проекта (можно найти в предыдущих вопросах). Ниже приведен код, относящийся к 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-канала.
Разместил бы изображение, если бы у меня было достаточно репутации.