我目前正在尝试将RSS Feed作为XML文件下载,我尝试使用RXJava而不是AsyncTask来解析和下载该文件。
我在主线程错误上找到了一个网络,但是我正试图拉下来。
以下是主要活动中的observable相关代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.rv_test_items);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
final ArrayList<TestItem> testItems = new ArrayList<>();
//testItems.add(new TestItem("Title here", "Content here"));
RssReader reader = new RssReader("http://www.feedforall.com/sample.xml");
// Subscribe on a new background thread, while returning the result on the UI thread.
// Using the RSS Classes we will pull the rss items from the rss feed and then create our
// own TestItem from them.
try {
Observable
.from(reader.getItems())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<RssItem>() {
@Override
public void call(RssItem item) {
TestItem newItem = new TestItem(item.getTitle(), item.getDescription());
testItems.add(newItem);
}
});
} catch (Exception e) {
e.printStackTrace();
Log.e("App", "Failed to download RSS Items");
}
TestItemAdapter testItemAdapter = new TestItemAdapter(testItems);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(testItemAdapter);
这是我的RSSReader类
public class RssReader {
private String rssUrl;
public RssReader(String url) {
rssUrl = url;
}
public List<RssItem> getItems() throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
//Creates a new RssHandler which will do all the parsing.
RssHandler handler = new RssHandler();
//Pass SaxParser the RssHandler that was created.
saxParser.parse(rssUrl, handler);
return handler.getRssItemList();
}
}
我的RSSHandler类
public class RssHandler extends DefaultHandler {
private List<RssItem> rssItemList;
private RssItem currentItem;
private boolean parsingTitle;
private boolean parsingLink;
private boolean parsingDescription;
public RssHandler() {
//Initializes a new ArrayList that will hold all the generated RSS items.
rssItemList = new ArrayList<RssItem>();
}
public List<RssItem> getRssItemList() {
return rssItemList;
}
//Called when an opening tag is reached, such as <item> or <title>
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals("item"))
currentItem = new RssItem();
else if (qName.equals("title"))
parsingTitle = true;
else if (qName.equals("link"))
parsingLink = true;
else if (qName.equals("description"))
parsingDescription = true;
else if (qName.equals("media:thumbnail") || qName.equals("media:content") || qName.equals("image")) {
if (attributes.getValue("url") != null)
currentItem.setImageUrl(attributes.getValue("url"));
}
}
//Called when a closing tag is reached, such as </item> or </title>
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals("item")) {
//End of an item so add the currentItem to the list of items.
rssItemList.add(currentItem);
currentItem = null;
} else if (qName.equals("title"))
parsingTitle = false;
else if (qName.equals("link"))
parsingLink = false;
else if (qName.equals("description"))
parsingDescription = false;
}
//Goes through character by character when parsing whats inside of a tag.
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (currentItem != null) {
//If parsingTitle is true, then that means we are inside a <title> tag so the text is the title of an item.
if (parsingTitle)
currentItem.setTitle(new String(ch, start, length));
//If parsingLink is true, then that means we are inside a <link> tag so the text is the link of an item.
else if (parsingLink)
currentItem.setLink(new String(ch, start, length));
//If parsingDescription is true, then that means we are inside a <description> tag so the text is the description of an item.
else if (parsingDescription)
currentItem.setDescription(new String(ch, start, length));
}
}
}
堆栈跟踪
10-07 11:39:15.040 1959-1959/? I/art: Late-enabling -Xcheck:jni
10-07 11:39:15.208 1959-1959/? W/System.err: java.io.IOException: Couldn't open http://www.feedforall.com/sample.xml
10-07 11:39:15.208 1959-1959/? W/System.err: at org.apache.harmony.xml.ExpatParser.openUrl(ExpatParser.java:755)
10-07 11:39:15.208 1959-1959/? W/System.err: at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:292)
10-07 11:39:15.208 1959-1959/? W/System.err: at javax.xml.parsers.SAXParser.parse(SAXParser.java:390)
10-07 11:39:15.208 1959-1959/? W/System.err: at javax.xml.parsers.SAXParser.parse(SAXParser.java:266)
10-07 11:39:15.208 1959-1959/? W/System.err: at com.polymorphicinc.retrofitsample.rss.RssReader.getItems(RssReader.java:36)
10-07 11:39:15.208 1959-1959/? W/System.err: at com.polymorphicinc.retrofitsample.ui.MainActivity.onCreate(MainActivity.java:47)
10-07 11:39:15.208 1959-1959/? W/System.err: at android.app.Activity.performCreate(Activity.java:5990)
10-07 11:39:15.208 1959-1959/? W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
10-07 11:39:15.208 1959-1959/? W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
10-07 11:39:15.208 1959-1959/? W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
10-07 11:39:15.208 1959-1959/? W/System.err: at android.app.ActivityThread.access$800(ActivityThread.java:151)
10-07 11:39:15.208 1959-1959/? W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
10-07 11:39:15.208 1959-1959/? W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
10-07 11:39:15.208 1959-1959/? W/System.err: at android.os.Looper.loop(Looper.java:135)
10-07 11:39:15.208 1959-1959/? W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5254)
10-07 11:39:15.208 1959-1959/? W/System.err: at java.lang.reflect.Method.invoke(Native Method)
10-07 11:39:15.209 1959-1959/? W/System.err: at java.lang.reflect.Method.invoke(Method.java:372)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
10-07 11:39:15.209 1959-1959/? W/System.err: Caused by: android.os.NetworkOnMainThreadException
10-07 11:39:15.209 1959-1959/? W/System.err: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
10-07 11:39:15.209 1959-1959/? W/System.err: at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
10-07 11:39:15.209 1959-1959/? W/System.err: at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
10-07 11:39:15.209 1959-1959/? W/System.err: at java.net.InetAddress.getAllByName(InetAddress.java:215)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.okhttp.HostResolver$1.getAllByName(HostResolver.java:29)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:232)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:124)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:272)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:382)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:332)
10-07 11:39:15.209 1959-1959/? W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:199)
10-07 11:39:15.209 1959-1959/? W/System.err: at org.apache.harmony.xml.ExpatParser.openUrl(ExpatParser.java:753)
10-07 11:39:15.209 1959-1959/? W/System.err: ... 18 more
10-07 11:39:15.209 1959-1959/? E/App: Failed to download RSS Items
10-07 11:39:15.215 1959-1978/? D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
10-07 11:39:15.216 1959-1959/? D/: HostConnection::get() New Host Connection established 0xb42d9a00, tid 1959
10-07 11:39:15.219 1959-1959/? D/Atlas: Validating map...
10-07 11:39:15.281 1959-1978/? D/libEGL: loaded /system/lib/egl/libEGL_emulation.so
10-07 11:39:15.282 1959-1978/? D/libEGL: loaded /system/lib/egl/libGLESv1_CM_emulation.so
10-07 11:39:15.286 1959-1978/? D/libEGL: loaded /system/lib/egl/libGLESv2_emulation.so
10-07 11:39:15.295 1959-1978/? D/: HostConnection::get() New Host Connection established 0xb42d9b90, tid 1978
10-07 11:39:15.311 1959-1978/? I/OpenGLRenderer: Initialized EGL, version 1.4
10-07 11:39:15.360 1959-1978/? D/OpenGLRenderer: Enabling debug mode 0
10-07 11:39:15.381 1959-1978/? W/EGL_emulation: eglSurfaceAttrib not implemented
10-07 11:39:15.381 1959-1978/? W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xb424bb40, error=EGL_SUCCESS
答案 0 :(得分:2)
看看这个以了解如何做到这一点:
public class RssReader {
private String rssUrl;
public RssReader(String url) {
rssUrl = url;
}
public Observable<List<RssItem>> getItems() {
return Observable.create(new Observable.OnSubscribe<List<RssItem>>() {
@Override
public void call(Subscriber<? super List<RssItem>> subscriber) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
//Creates a new RssHandler which will do all the parsing.
RssHandler handler = new RssHandler();
//Pass SaxParser the RssHandler that was created.
saxParser.parse(rssUrl, handler);
subscriber.onNext(handler.getRssItemList());
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(e);
}
}
});
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.rv_test_items);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
RssReader reader = new RssReader("http://www.feedforall.com/sample.xml");
reader.getItems()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<RssItem>>() {
@Override
public void call(List<RssItem> items) {
final ArrayList<TestItem> testItems = new ArrayList<>(items.size());
for (int size = items.size(), i = 0; i < size; i++) {
RssItem item = items.get(i);
testItems.add(new TestItem(item.getTitle(), item.getDescription()));
}
recyclerView.setAdapter(new TestItemAdapter(testItems));
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable e) {
e.printStackTrace();
Log.e("App", "Failed to download RSS Items");
}
});
}
答案 1 :(得分:0)
试试这个
Observable.defer(() -> Observable.from(reader.getItems())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<RssItem>() {
@Override
public void call(RssItem item) {
TestItem newItem = new TestItem(item.getTitle(), item.getDescription());
testItems.add(newItem);
}
});