现在我正在创建一个 RSS 阅读器,主要是尝试获取项目的标题和描述以显示在 ListView 上。我之前在没有 RSS 数据的情况下对其进行了测试,并确认该应用程序正确列出了我创建的项目。然而,在尝试对 RSS 中的数据执行相同操作后,我在检索实际 RSS 数据以及如何使用 doinBackground 方法时遇到了问题。
阅读 Google 关于 doinBackground 的文档后,我了解到它的类(异步)允许执行后台操作并将其结果显示在 UI 线程中。然而,我在提取 RSS 数据以及 doinBackground() 如何适应我的代码时遇到了一般问题。关于如何正确检索数据并有效使用 doinbackground() 有什么想法吗?
我遇到问题的代码类是 Headlines 和 RSSManager。代码如下:
标题 fragment
import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import java.net.MalformedURLException;
import java.net.URL;
public class Headlines extends Fragment {
EditText editText;
Button gobutton;
ListView listView;
public Headlines() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_headlines, container, false);
editText = (EditText)v.findViewById(R.id.urlText);
gobutton = (Button)v.findViewById(R.id.goButton);
listView = (ListView)v.findViewById(R.id.listView);
RSSFeedManager rfm = new RSSFeedManager();
News [] news = new News[100]; // i shouldnt have to set the size of the array here since I did it in getFeed() in RSSFeedManager.java
try {
news = rfm.getFeed(String.valueOf(new URL("http://rss.cnn.com/rss/cnn_world.rss")));
} catch (MalformedURLException e) {
e.printStackTrace();
}
RssAdapter adapter = new RssAdapter(this.getActivity(),news);
listView.setAdapter(adapter);
/*gobutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});*/
return v;
}
}
RSSFeedManager
import android.os.AsyncTask;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class RSSFeedManager extends AsyncTask<String,Void,String> {
public URL rssURL;
News[] articles;
public News[] getFeed(String url) {
try {
String strURL = url;
rssURL = new URL(url);
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(rssURL.openStream());
//using Nodelist to get items within the rss, then creating
//a News array the same size of the amount of items within the rss
//then setting up a temporary "News" item which will be the temp object
//used for storing multiple objects that contain title and description
//of each item
NodeList items = doc.getElementsByTagName("item");
News[] articles = new News[items.getLength()];
News news = null;
//traverse through items and place the contents of each item within an RssItem object
//then add to it to the News Array
for (int i = 0; i < items.getLength(); i++) {
Element item = (Element) items.item(i);
news.setTitle(getValue(item, "title"));
news.setDescription(getValue(item, "description"));
articles[i] = news;
}
} catch (Exception e) {
e.printStackTrace();
}
return articles;
}
public String getValue(Element parent, String nodeName) {
return parent.getElementsByTagName(nodeName).item(0).getFirstChild().getNodeValue();
}
@Override
protected String doInBackground(String... url) {
String rssURL = url[0];
URL urlTemp;
try {
//pulling the url from the params and converting it to type URL and then establishing a connection
urlTemp = new URL(rssURL);
HttpURLConnection urlConnection = (HttpURLConnection) urlTemp.openConnection();
urlConnection.connect();
/*
*im thinking i need to call the getFeed() method
*after establishing the httpurlconnection however
*I also thought I may just need to move the getFeed()
*code within doinBackground. Lost at this point due to the
* return types of getFeed and doinBackground
*/
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
最佳答案
拆开每一行代码后,我发现了 RSSFeedManager 类、doInBackground()
方法和 Headlines 类的一些问题。
从 RSSFeedManager 开始,这里出现了一些问题。我将 News []articles
实例化为类变量,然后在 getFeeds()
方法中重新定义它。显然,这会导致一些问题,并将 articles
返回为 null。我还删除了 strURL
和 rssURL
因为我的处理方式完全错误。不需要将 URL 传递给 getFeeds()
,而是需要从 URL 传递 XML。我还稍微修改了代码以使用 News 类的构造函数。
这是 RSSFeedManager 的固定代码:
public class RSSFeedManager{
News[] articles;
public News[] getFeed(String html) {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new ByteArrayInputStream(html.getBytes()));
NodeList items = doc.getElementsByTagName("item");
articles = new News[items.getLength()];
for (int i = 0; i < items.getLength(); i++) {
Element item = (Element) items.item(i);
News news = new News(getValue(item, "title"),getValue(item, "description").substring(0,100),"");
articles[i] = news;
}
} catch (Exception e) {
//e.printStackTrace();
Log.d("EXCEPTION PARSING",e.toString());
}
return articles;
}
public String getValue(Element parent, String nodeName) {
return parent.getElementsByTagName(nodeName).item(0).getFirstChild().getNodeValue();
}
}
正如我之前提到的,我意识到 RSSFeedManager 应该从 URL 而不是 URL 本身接收 XML,并且新类是 doInBackground()
应该发生的地方。本质上,Downloader 类的 doInBackground()
方法(扩展了 AsyncTask
)正在接收输入的 url,然后从该 RSS url 收集 XML。
这是下载器类
public class Downloader extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
String result ="";
try{
URL url = new URL(urls[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while((line=reader.readLine())!= null){
result= result + line;
}
connection.disconnect();
} catch (Exception e) {
Log.e("Error fetching", e.toString());
}
return result;
}
}
因此,在这两门类(class)都完成之后,我知道我需要在 Headlines 类(class)中解决一些问题。我最初对代码进行了强制测试,以确保 RSS 提要中的文章能够正确显示,并且他们确实做到了,然后开始正确地实现它。提醒人们,该程序的目的是显示来自 RSS 提要的文章,用户通过将 url 输入到 editText
中指定,这是一个 EditText
对象。然后用户按下 Button
类型的 goButton
,然后列出来自 editText
的 url 的所有文章。我通过为 goButton
创建一个 onClickListener
并创建 Downloader
和 RssFeedManager
类的对象来实现此目的,以便调用它们的方法来建立连接、检索 URL 的 XML,然后对其进行解析。
这是 Headline 类的代码 fragment ,我可以将所有内容连接在一起。
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_headlines, container, false);
editText = (EditText)v.findViewById(R.id.urlText);
gobutton = (Button)v.findViewById(R.id.goButton);
listView = (ListView)v.findViewById(R.id.listView);
parent = this.getActivity();
gobutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RSSFeedManager rfm = new RSSFeedManager();
String html = "";
try {
Downloader d = new Downloader();
d.execute(editText.getText().toString());
html = d.get();
Log.d("HTML CAME BACK", html);
news = rfm.getFeed(html);
RssAdapter adapter = new RssAdapter(parent, news);
listView.setAdapter(adapter);
} catch (InterruptedException e) {
Log.e("ERROR!!!!!", e.toString());
} catch (ExecutionException e) {
Log.e("ERROR!!!!!!!", e.toString());
Toast.makeText(parent, e.toString(), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e("WEIRD!", e.toString());
Toast.makeText(parent, e.toString(), Toast.LENGTH_LONG).show();
}
}
});
所有这些更改都帮助解决了问题,让我能够进一步完成这个程序,并了解有关 Android 开发的更多信息。
关于java - 如何正确利用 doinBackground() 方法来检索 RSS 项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33276540/