1

I have two files XMLParser that parse XML from URL and the Activity. Seems the getter methods don't work. I can output the values of the arrayList in XMLParser files. but not in Activity file.

public class XMLParser extends AsyncTask<Void, Void, ArrayList<Object>> {

    ArrayList<String> groupItem = new ArrayList<String>();
    ArrayList<Object> childItem = new ArrayList<Object>();
    ArrayList<String> child = new ArrayList<String>();


    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
            System.out.println("authType is " + authType);
            System.out.println("cert issuers");
            for (int i = 0; i < certs.length; i++) {
                System.out.println("\t"
                        + certs[i].getIssuerX500Principal().getName());
                System.out.println("\t" + certs[i].getIssuerDN().getName());
            }
        }
    } };

    @Override
    protected ArrayList<Object> doInBackground(Void... params) {

        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection
                    .setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        try {
            URL url = new URL();
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(new InputSource(url.openStream()));
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getElementsByTagName("Device");
            for (int i = 0; i < nodeList.getLength(); i++) {
                Element deviceElement = (Element) nodeList.item(i);
                groupItem.add(deviceElement.getAttribute("serial"));
                child = new ArrayList<String>();
                child.add(deviceElement.getAttribute("model"));
                child.add(deviceElement.getAttribute("asset"));
                child.add(deviceElement.getAttribute("location"));
                child.add(deviceElement.getAttribute("lastConnected"));
                childItem.add(child);
            }
;
        } catch (Exception e) {
            System.out.println("XML Pasing Excpetion = " + e);
        }
        return childItem;
    }

    protected void onPostExecute() {
        // here you will get the result
    }

    public ArrayList<String> getGroupItem() {

        return groupItem;
    }

    public ArrayList<Object> getChildItem() {
        return childItem;
    }

Here is Activity file:

public class DevicesActivity extends ExpandableListActivity implements
OnChildClickListener  {
    ArrayList<String> groupItem = new ArrayList<String>();
    ArrayList<Object> childItem = new ArrayList<Object>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /** Create a new layout to display the view */
         //setContentView(R.layout.activity_devices);

        //ExpandableListView expandbleLis = getExpandableListView();
        //expandbleLis.setDividerHeight(2);
        //expandbleLis.setGroupIndicator(null);
        //expandbleLis.setClickable(true);
        startXMLParser();

        System.out.println("size in Device "+groupItem.size());
        System.out.println("size in Device "+childItem.size());



    }
    private void startXMLParser() {
        XMLParser XMLTask = new XMLParser();
        XMLTask.execute(null,null,null);
        groupItem=XMLTask.getGroupItem();
        childItem=XMLTask.getChildItem();
}

Get ArrayList:

public void getArrayList(ArrayList<DataInterface> lst) {
        finalList=lst;

    }
Michael
  • 355
  • 2
  • 4
  • 16

2 Answers2

1

Since AyncTask is asynchronous there is no guarantee that the results will be there when you call your methods to retrieve the data, in fact, it probably won't be. You need to make sure that the task has completed before trying to access those variables.

One solution would be to pass that data on to the Activity in onPostExecute(). If this class is an inner class of the Activity then you can have member variables and assign them in onPostExecute() or another AsyncTask method.

Also, you should have the parameter type in your onPostExecute() declaration or it won't receive the results. And you should add the @Override annotation

@Override
protected void onPostExecute(ArrayList<Object> result) {
    // here you will get the result
}

In AsyncTask create a constructor to receive Context

Activity mAct;
public calss MyTask extends AsyncTask<...>  // you know what to add here
{
    public MyTask(Activity act)
    {
         mAct = act;
    }

then use mContext in onPostExecute() to call your Activity function

When you create the task

MyTask task = new MyTask(this);  // pass context to constructor
taske.execute(// add params);

public void onPostExecute(ArrayList<Object> result){
    mAct.yourMethod(result);
codeMagic
  • 44,549
  • 13
  • 77
  • 93
  • Thanks. You mean to make the onPostExecute method inside AyncTask class return the data and then call onPostExecute in the main activity? – Michael May 31 '13 at 14:27
  • No, `onPostExecute()` receives the returned `result` from `doInBackground()` but right now you aren't overriding it with the correct `params` you declared when you defined your `AsyncTask`, the last `param` in the class header. So it is like it is a function you defined yourself – codeMagic May 31 '13 at 14:29
  • If its an inner class then no problem, you can assign a member variable of the `Activity` to the result. If its a separate file then you need to pass a reference to that `Activity` in the `AsyncTask` constructor to update the `Activity` from `onPostExecute()` – codeMagic May 31 '13 at 14:31
  • I see, I corrected them. How can I get the result in the Main Activity? – Michael May 31 '13 at 14:31
  • Add a constructor to your `AsyncTask` that accepts `Context` as a `param` then use that to call a function in `Activity` from `onPostExecute()`. Then when you create your instance of `AsyncTask` pass it 'this' – codeMagic May 31 '13 at 14:38
  • Thanks. It's very helpful, but I'm not sure what do you mean by use Context to call a function in Activity – Michael May 31 '13 at 15:01
  • I think I got going a little quick. See my updated answer. Something like that should work – codeMagic May 31 '13 at 15:09
  • Thanks. but it seems doesn't work. the arraylist size is zero. I update my get ArrayList mathod – Michael May 31 '13 at 15:20
  • Where do you call that method? Have you checked the size in `doInBackground()` and in `onPostExecute()`? – codeMagic May 31 '13 at 15:27
  • Yes, the size inside onPostExecute() is correct. I call the method inside onPostExecute() myAct.getArrayList(result); then just execute the XMLparser in Activity and print the finalList. the finalList doesn't hold the data..... – Michael May 31 '13 at 15:33
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/30997/discussion-between-codemagic-and-michael) – codeMagic May 31 '13 at 15:37
  • I know what happened. I printed the size inside getArrayList method. it outputs the correct size. I tried to print the finalList inside onCreate method. the list is empty. How is it possible? I called the XMLparser.execute before my print statement. – Michael May 31 '13 at 15:38
0

Following Example Give You Idea

@Override
    protected void onPostExecute(ArrayList<Object> result) {
        // here you will get the result               ||    This Must Be Same
    }                                                 \/ 
    protected                          ArrayList<Object> doInBackground(String... params)

Return type of doInBackground and Parameter of PostExecute must be Same

UnderGround
  • 450
  • 1
  • 3
  • 17