简体   繁体   中英

RXJava Android - Network exception when trying to pull RSS feed

I currently am trying to pull down an RSS Feed as an XML file and I'm trying to use RXJava instead of an AsyncTask to parse and download the file.

I'm getting a network on the main thread error though while I'm trying to pull the feed down.

Here is the relevant code with observable which is in the main activity

@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);

And here is my RSSReader class

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();
    }
}

And my RSSHandler class

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));
        }
    }
}

Stack trace

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

Take a look at this to get an idea how to do it:

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");
                }
            });
}

try this

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);
                    }
                });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM