0

I was calling a class which was performing network operations on the main thread, causing my app to blow up on more recent devices. So I've tried moving the call to the class into a AsyncTask inner class in my main activity. However now i'm getting null reference expections.

Here's my AsyncTask:

      private class RetreiveAmazonNodesXML extends AsyncTask {

        private Exception exception;

        @Override
        protected Object doInBackground(Object... params) {
               try {
                    childrenBrowseNodesXml = new Amazon(browseNodeId, locality);

                } catch (Exception e) {
                    this.exception = e;
                }
            return null;
        }


     }

And here's where I call it in my activity:

 RetreiveAmazonNodesXML test = new RetreiveAmazonNodesXML();
 test.execute();
 parseXmlFile(childrenBrowseNodesXml.getBrowseNodesXML());

childrenBrowseNodesXml isn't getting updated and returning null. I know my Amazon class works fine so its something im doing with AsyncTask, but I have no idea?

KingFu
  • 1,358
  • 5
  • 22
  • 42
  • have a look at my example here about how to execute an Async task and how to get its result in a callback function: http://stackoverflow.com/questions/13713751/json-object-null-android-asynctask/13713852#13713852 – lahsrah Apr 17 '13 at 10:38
  • Your code prevents you to see if there's an exception thrown. Put some log in your catch Exception (or better, [remove this](http://stackoverflow.com/questions/21938/is-it-really-that-bad-to-catch-a-general-exception)). – m0skit0 Apr 17 '13 at 10:38
  • Pass generic tag, class RetreiveAmazonNodesXML extends AsyncTask. – Vishesh Chandra Apr 17 '13 at 10:41
  • You need normally async task? – SBotirov Apr 17 '13 at 11:01

3 Answers3

2

Use callback for get result from async task. Here interface callback class:

public interface Callback {
    public void onSuccess(Object data);
    public void onError(String errorMsg);
}

And create instance this class and implement its:

final Callback resCallback = new Callback() {
    @Override
public void onSuccess(Object data) {
    parseXmlFile(data);
}

@Override
public void onError(String errorMsg) {
    //show error with Alert or Toast
}
};

And create asynctask class with your callback:

RetreiveAmazonNodesXML test = new RetreiveAmazonNodesXML(resCallback);
test.execute(yourObjectsParams);

Write asynctask class like this:

private class RetreiveAmazonNodesXML extends AsyncTask {
    private Callback responderCallback;
    private Exception exception;

    public GeneralHttpTask(Callback callback){
        this.responderCallback = callback;
    }

    @Override
    protected Object doInBackground(Object... params) {
           try {
                Amazon childrenBrowseNodesXml = new Amazon(browseNodeId, locality);
                return childrenBrowseNodesXml;
            } catch (Exception e) {
                this.exception = e;
            }
        return null;
    }

    @Override
    protected void onPostExecute(Object result) {
        if(result != null) {
            responderCallback.onSuccess(result);
        } else {
            responderCallback.onError(exception);
        }
    }
}
SBotirov
  • 13,872
  • 7
  • 59
  • 81
  • Thanks for your answer. Just wondering what's the benifit of a callback interface when AsyncTask provides onPostExecute()? – KingFu Apr 17 '13 at 11:42
  • Example you want use general AsyncTask class in more activities yes, then you need create a general AsyncTask class and send its url and callback, when callback come then you make use result. If you want separately create AsyncTask class – SBotirov Apr 17 '13 at 11:49
1

It is because you're trying to use the value that AsyncTask hasn't returned, as AsyncTask is running asyncronously.

You should put parseXmlFile(childrenBrowseNodesXml.getBrowseNodesXML()); into your AsyncTask's onPostExecute() method, like this:

  private class RetreiveAmazonNodesXML extends AsyncTask {

    private Exception exception;

    @Override
    protected Object doInBackground(Object... params) {
           try {
                childrenBrowseNodesXml = new Amazon(browseNodeId, locality);

            } catch (Exception e) {
                this.exception = e;
            }
        return null;
    }

    @Override
    protected void onPostExecute(Object obj) {

           parseXmlFile(childrenBrowseNodesXml.getBrowseNodesXML());

    }

 }

Also, return null in doInBackground method may not be a good manner, the stuff that doInBackground returns will be passed as a parameter to onPostExecute() method automatically by AsyncTask.

For more about the AsyncTask, please refer to the Android Developers: AsyncTask

dumbfingers
  • 7,001
  • 5
  • 54
  • 80
  • this did the trick thanks! should of known it would be something to do with multi-threading messing my code up again. Had to add more code to onPostExecute, which has now resulted in a problem with a spinner not updating...eurgh! – KingFu Apr 17 '13 at 11:40
0

The problem is, that you create a background thread (AsyncTask) that fills the childrenBrowseNodesXml after a while (when it's actually executed), but you try to use it immediately in your activity code.

Move your parseXMLFile to onPostExecute(Void result) method of AsyncTask instead.

lopisan
  • 7,720
  • 3
  • 37
  • 45