简体   繁体   English

从内部AsyncTask类获取Arraylist

[英]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. 我已经在Asynctask解析了一些XML数据并将其打印在日志中,但是每当我尝试将ArrayList数据复制到我的Activity中时,它始终保持为空。

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. 我尝试在onPostExecute方法中调用Activity的onPostExecute方法,但它不起作用。

1) You should declare the ArrayList variable as a member of mainActivity and then pass its reference into the Asynctask. 1)您应该将ArrayList变量声明为mainActivity的成员, 然后将其引用传递给Asynctask。

2) You can verify that the data is present in the list, only after you are sure the Asynctask has completed processing. 2)只有在确保Asynctask已完成处理之后,才能验证列表中是否存在数据。 (You can do that within the onPostExecute of the AsyncTask). (您可以在AsyncTask的onPostExecute中执行此操作)。

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. 如果您将其填充在ListView AdapterView类的AdapterView ,请记住在准备好数据集后调用adapter.notifyDataSetChanged()

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. 实际上,您可以将doInBackground()的结果传递给onPostExecute()以继续在调用线程(您的情况下的主线程onPostExecute()上进行工作。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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