【问题标题】:Getting an Arraylist from an inner AsyncTask class从内部 AsyncTask 类获取 Arraylist
【发布时间】:2016-10-29 06:06:33
【问题描述】:

我已经解析了Asynctask 中的一些XML 数据并将其打印在日志中,但是每当我尝试将数据的ArrayList 复制到我的活动中时,它始终保持为空。

这是代码,

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

    }

}

我尝试在onPostExecute方法中调用Activity的静态方法,不行。

【问题讨论】:

  • 什么不起作用?您在哪里使用数据?

标签: java android arraylist android-asynctask


【解决方案1】:

1) 您应该将 ArrayList 变量声明为 mainActivity 的成员,然后将其引用传递给 Asynctask。

2) 只有在您确定 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;
    }

【讨论】:

  • 但 ArrayListmyData 必须是静态的,因为我在下面的静态方法中使用它。我也应该从方法中删除静态吗?
  • @Mufad :是的,在这种情况下,静态前缀似乎是不必要的。该方法不必是静态的。您可以在 AsyncTask 中调用该方法,而无需为其添加 MainActivity
  • @Mufad :如果您满意,请接受答案。否则,如果您需要进一步说明,请告诉我。
【解决方案2】:

尽可能避免使用静态变量。不必要的静态字段会让您陷入难以理解的问题。

如果您将其填充到AdapterView 中,例如ListView,请记住在准备好数据集后调用adapter.notifyDataSetChanged()

您实际上可以将 doInBackground() 的结果传递给 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();

或者您甚至可以设置侦听器并以更复杂的方式进行操作,例如:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多