0

I have been creating an app recently that I am working on. The app simply shows the contents of a RSS feed in a ListView where the list items is clickable. It worked on Android 3.0 and below, but once i upgraded my app and device to 4.0 and above, it failed. I can see that I need to use a custom thread because of the NetworkOnMainThreadException, so I have chosen AsyncTask. I simply have a listview in my XML with id android:id/list and the code I use to load the feed looks like this:

//Load RSS news feed
// Initializing instance variables
        headlines = new ArrayList();
        links = new ArrayList();

        try {
            URL url = new URL("http://www.vg.no/rss/create.php?categories=25,10,49,26,23,20,21,12,32,30,34&keywords=85,98,1724,84,476,821,820,512,8317,343&limit=15");

            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            factory.setNamespaceAware(false);
            XmlPullParser xpp = factory.newPullParser();

                // We will get the XML from an input stream
            xpp.setInput(getInputStream(url), "UTF_8");

                /* We will parse the XML content looking for the "<title>" tag which appears inside the "<item>" tag.
                 * However, we should take in consideration that the rss feed name also is enclosed in a "<title>" tag.
                 * As we know, every feed begins with these lines: "<channel><title>Feed_Name</title>...."
                 * so we should skip the "<title>" tag which is a child of "<channel>" tag,
                 * and take in consideration only "<title>" tag which is a child of "<item>"
                 *
                 * In order to achieve this, we will make use of a boolean variable.
                 */
            boolean insideItem = false;

                // Returns the type of current event: START_TAG, END_TAG, etc..
            int eventType = xpp.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                if (eventType == XmlPullParser.START_TAG) {

                    if (xpp.getName().equalsIgnoreCase("item")) {
                        insideItem = true;
                    } else if (xpp.getName().equalsIgnoreCase("title")) {
                        if (insideItem)
                            headlines.add(xpp.nextText()); //extract the headline
                    } else if (xpp.getName().equalsIgnoreCase("link")) {
                        if (insideItem)
                            links.add(xpp.nextText()); //extract the link of article
                    }
                }else if(eventType==XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){
                    insideItem=false;
                }

                eventType = xpp.next(); //move to next element
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Binding data
        ArrayAdapter adapter = new ArrayAdapter(this,
                android.R.layout.simple_list_item_1, headlines);

        setListAdapter(adapter);
    } catch (RuntimeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        Toast.makeText(getApplicationContext(), "Cannot load news, please check internett connection", Toast.LENGTH_LONG).show();
    }

I have been trying to understand it; however, I cannot get it to work. If someone could please help me put all of this in AsyncTask and call the RSS refresh on onCreate() and on onClick() and explain how, it would be great.

Thanks!

APerson
  • 8,140
  • 8
  • 35
  • 49
user1446632
  • 417
  • 2
  • 9
  • 24
  • Is the code above part of the AsyncTask `doInBackground()`? You're not allowed to set the adapter from this method - it's running in a different thread. And an AsyncTask has a logical method of execution, what exactly are you having trouble with? Have you tried anything? – A--C Jan 25 '13 at 16:58
  • No, none of the code above is in AsyncTask, i have tried to place it there, but i just get a ton of errors and nothing works. – user1446632 Jan 25 '13 at 17:01
  • I suggest you post what you have tried and the errors you're getting. – A--C Jan 25 '13 at 17:05

1 Answers1

2

this is a boilerplate inline AsyncTask method

new AsyncTask<Void, Void, Void>({

//initialize headlines here or outside of here or before this Asynctask
    headlines = new ArrayList();
    links = new ArrayList();

@Override
protected Void doInBackground(Void... params)

 try {
        URL url = new URL("http://www.vg.no/rss/create.php?categories=25,10,49,26,23,20,21,12,32,30,34&keywords=85,98,1724,84,476,821,820,512,8317,343&limit=15");

        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(false);
        XmlPullParser xpp = factory.newPullParser();

            // We will get the XML from an input stream
        xpp.setInput(getInputStream(url), "UTF_8");

            /* We will parse the XML content looking for the "<title>" tag which appears inside the "<item>" tag.
             * However, we should take in consideration that the rss feed name also is enclosed in a "<title>" tag.
             * As we know, every feed begins with these lines: "<channel><title>Feed_Name</title>...."
             * so we should skip the "<title>" tag which is a child of "<channel>" tag,
             * and take in consideration only "<title>" tag which is a child of "<item>"
             *
             * In order to achieve this, we will make use of a boolean variable.
             */
        boolean insideItem = false;

            // Returns the type of current event: START_TAG, END_TAG, etc..
        int eventType = xpp.getEventType();
        while (eventType != XmlPullParser.END_DOCUMENT) {
            if (eventType == XmlPullParser.START_TAG) {

                if (xpp.getName().equalsIgnoreCase("item")) {
                    insideItem = true;
                } else if (xpp.getName().equalsIgnoreCase("title")) {
                    if (insideItem)
                        headlines.add(xpp.nextText()); //extract the headline
                } else if (xpp.getName().equalsIgnoreCase("link")) {
                    if (insideItem)
                        links.add(xpp.nextText()); //extract the link of article
                }
            }else if(eventType==XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){
                insideItem=false;
            }

            eventType = xpp.next(); //move to next element
        }

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (XmlPullParserException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}

@Override
protected Void onPostExecute() //UI THREAD STUFF , onPostExecute may need an argument, not sure yet though
    ArrayAdapter adapter = new ArrayAdapter(this,
            android.R.layout.simple_list_item_1, headlines);

    setListAdapter(adapter);
}

}).execute();

good luck, you can put a loading progress bar in onPreExecute()

CQM
  • 42,592
  • 75
  • 224
  • 366
  • Thanks so much for the code, but in the doInBackground method, it says "void..." what does the 3 dots mean? Should they be there? – user1446632 Jan 25 '13 at 17:11
  • This is why we don't simply hand out code without explanation. `Void...` is called `varargs` in Java, it allows you to specify a different amount of arguments. – A--C Jan 25 '13 at 17:14
  • Thanks alot for help, but could you try to explain? Where should i put it? Cause when i put in the onCreate(), i get errors as well as if i put it after like the onClick() method – user1446632 Jan 25 '13 at 17:15
  • @A--C this is a boilerplate AsyncTask, there is literally no other way to write it. you can edit it if you want, make it a collaborative effort – CQM Jan 25 '13 at 17:18
  • CQM, could you try to explain where i should put it, and what you mean my Void... I really need help here – user1446632 Jan 25 '13 at 17:18
  • @user1446632 Void... is basically an array, its different syntax for an Array, I've only seen it used within AsyncTasks though. Since you are using Void... you don't have to worry about passing values through it. oh except you have to return null or something in doInBackGround – CQM Jan 25 '13 at 17:19
  • @user1446632 post your whole onCreate method in `www.pastebin.com` – CQM Jan 25 '13 at 17:22
  • @CQM `...` it is like an array when you acess from *inside* the method. Eg if you have `public void method (String... args)` you can call it via `method ("one-arg")`, `method ("one-arg","second-arg")`, etc. It's called `varargs` (variable arguments). – A--C Jan 25 '13 at 17:26
  • where in my code should all of the code be placed? Inside another method? Anywhere? – user1446632 Jan 25 '13 at 17:30
  • http://androidresearch.wordpress.com/2012/03/17/understanding-asynctask-once-and-forever/ – A--C Jan 25 '13 at 17:32
  • @user1446632 in OnCreate if you desire, after you initialize your lsitview – CQM Jan 25 '13 at 17:36
  • Yeah, but once i do, i get alot of errors, see pastebin: http://pastebin.com/FrKt2weS – user1446632 Jan 25 '13 at 17:49
  • @user1446632 see A--C's link http://androidresearch.wordpress.com/2012/03/17/understanding-asynctask-once-and-forever/ – CQM Jan 25 '13 at 18:41