简体   繁体   中英

Getting an Arraylist from an inner AsyncTask class

I've parsed some XML Data in Asynctask and printed it in the log, but whenever I try to copy the ArrayList of data into my Activity, it always remains null.

Here's the code,

public class MainActivity extends AppCompatActivity {

   static ArrayList<NewsItems>myData=new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ReadRss readRss = new ReadRss(this);
        readRss.execute();
       Log.d("TAG", String.valueOf(myData.size()));//This stays empty
    }


    public static void getData(ArrayList<NewsItems>items){
        for (int i=0; i<items.size(); i++){
            myData.add(items.get(i));
        }
    }
    class ReadRss extends AsyncTask<Void, Void, Void>{

         ArrayList<NewsItems>feedItems = new ArrayList<>();
        Context context;
        String address = "http://www.thedailystar.net/frontpage/rss.xml";
        ProgressDialog progressDialog;
        URL url;

        public ReadRss(Context context) {
            this.context = context;
            progressDialog = new ProgressDialog(context);
            progressDialog.setMessage("Loading...");
        }

        @Override
        protected void onPreExecute() {
            if(progressDialog!=null){
                if (!progressDialog.isShowing()){
                    progressDialog.show();
                }
            }
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            if(progressDialog!=null){
                if (progressDialog.isShowing()){
                    progressDialog.hide();
                }
            }
            MainActivity.getData(feedItems);
        }

        @Override
        protected Void doInBackground(Void... params) {
            ProcessXml(Getdata());
            return null;
        }

        private void ProcessXml(Document data) {

            if (data != null) {

                Element root = data.getDocumentElement();
                Node channel = root.getChildNodes().item(1);
                NodeList items = channel.getChildNodes();
                for (int i = 0; i < items.getLength(); i++) {
                    Node currentchild = items.item(i);
                    if (currentchild.getNodeName().equalsIgnoreCase("item")) {
                        NewsItems item=new NewsItems();
                        NodeList itemchilds = currentchild.getChildNodes();
                        for (int j = 0; j < itemchilds.getLength(); j++) {
                            Node current = itemchilds.item(j);
                            if (current.getNodeName().equalsIgnoreCase("title")){
                                item.setTitle(current.getTextContent());
                            }else if (current.getNodeName().equalsIgnoreCase("description")){
                                item.setDescription(current.getTextContent());
                            }else if (current.getNodeName().equalsIgnoreCase("media:thumbnail")){
                                item.setMedia(current.getAttributes().getNamedItem("url").getTextContent());
                            }else if (current.getNodeName().equalsIgnoreCase("link")){
                                item.setUrl(current.getTextContent());
                            }
                        }
                        feedItems.add(item);
                        Log.d("itemTitle", item.getTitle());
                        Log.d("itemDescription",item.getDescription());
                        Log.d("itemMediaLink",item.getMedia());
                        Log.d("itemLink",item.getUrl());

                    }
                }
            }

        }



        public Document Getdata() {
            try {
                url = new URL(address);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                InputStream inputStream = connection.getInputStream();
                DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = builderFactory.newDocumentBuilder();
                Document xmlDoc = builder.parse(inputStream);
                return xmlDoc;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

    }

}

I tried calling a static method of the Activity in the onPostExecute method, it doesn't work.

1) You should declare the ArrayList variable as a member of mainActivity and then pass its reference into the Asynctask.

2) You can verify that the data is present in the list, only after you are sure the Asynctask has completed processing. (You can do that within the onPostExecute of the AsyncTask).

public class MainActivity extends AppCompatActivity {

ArrayList<NewsItems>myData=new ArrayList<>(); //No need for static

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ReadRss readRss = new ReadRss(this,myData); //Pass the list variable reference into the asynctask instance
    readRss.execute();
   Log.d("TAG", String.valueOf(myData.size()));//This will be empty due to concurrent call to asynctask, which executes parallel to main thread.
}


public void getData(ArrayList<NewsItems>items){//Static qualifier unneccessary here
    for (int i=0; i<items.size(); i++){
        myData.add(items.get(i));
    }
}
class ReadRss extends AsyncTask<Void, Void, Void>{

     ArrayList<NewsItems>feedItems = new ArrayList<>();
    Context context;
    String address = "http://www.thedailystar.net/frontpage/rss.xml";
    ProgressDialog progressDialog;
    URL url;

    public ReadRss(Context context,ArrayList<NewsItems> feedItems) {
        this.context = context;
        this.feedItems = feedItems; //Assign the reference of the list here so that modifications done within the Asynctask are reflected in the MainActivity
        progressDialog = new ProgressDialog(context);
        progressDialog.setMessage("Loading...");
    }

    @Override
    protected void onPreExecute() {
        if(progressDialog!=null){
            if (!progressDialog.isShowing()){
                progressDialog.show();
            }
        }
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        if(progressDialog!=null){
            if (progressDialog.isShowing()){
                progressDialog.hide();
            }


        }
   //Do whatever you need with the arraylist data here
        getData(feedItems);
    }

    @Override
    protected Void doInBackground(Void... params) {
        ProcessXml(Getdata());
        return null;
    }

Avoid static variables as much as possible. Unnecessary static fields land you into problems hard to understand.

If you are populating it in an AdapterView like ListView , remember to call adapter.notifyDataSetChanged() when you have the data set ready with you.

You can actually pass the result of your doInBackground() to onPostExecute() to continue doing your work on the calling thread, which is the main thread in your case.

new AsyncTask<Void, Void, ArrayList<NewsItems>>() {
    @Override
    protected ArrayList<NewsItems> doInBackground(Void... params) {
        ArrayList<NewsItems> response = whatEverMethodGetsMeNetworkCallResponse();

        return response;
    }

    @Override
    protected void onPostExecute(ArrayList<NewsItems> response) {
        super.onPostExecute(response);

        // Do whatever you want to do with the network response
    }
}.execute();

Or you can even set up listeners and do it in a more sophisticated way like:

onCreate() {
    ...

    getNewsItems(new NewsItemsListener() {
        void onFetched(ArrayList<NewsItems> items) {
            // Do whatever you want to do with your news items
        }
    });
}

public void getNewsItems(final NewsItemsListener listener)
    new AsyncTask<Void, Void, ArrayList<NewsItems>>() {
        @Override
        protected ArrayList<NewsItems> doInBackground(Void... params) {
            ArrayList<NewsItems> response = whatEverMethodGetsMeNetworkCallResponse();

            return response;
        }

        @Override
        protected void onPostExecute(ArrayList<NewsItems> response) {
            super.onPostExecute(response);

            listener.onFetched(response);
        }
    }.execute();
}

public interface NewsItemsListener {
    void onFetched(ArrayList<NewsItems> items);
}

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