informDataSetChanged Android中的AsyncTask内部出错

时间:2015-08-27 07:48:11

标签: android android-asynctask

我使用带有ListView的{​​{1}}在CustomAdapter中加载了很多项时出错了。

我在BaseAdapter方法中使用CustomAdapter

onPostExecute

当启动另一个class setProjectsFilesNamesMap extends AsyncTask<Void,Void,Void>{ @Override protected Void doInBackground(Void...voids) { //Fülle die Maps mit Daten for (int position = 0; position < projectFileNamesMap.size(); position++) { String filename = projectFileNamesMap.get(position); setJobMap(filename); setProjectMap(filename); } return null; } @Override protected void onPostExecute(Void v){ CustomAdapterProjects adapter = new CustomAdapterProjects(ProjectsList.context, projectMap, jobMap); setListAdapter(adapter); } } 并按下后退按钮时出现此错误并且应用程序崩溃:

Activity

修改 setMaps:

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes. [in ListView(16908298, class android.widget.ListView) with Adapter(class CustomAdapter.CustomAdapterProjects)]

getDOMElement:

public void setMaps(String filename) {

    XMLParser parser = new XMLParser();
    Document doc = parser.getDomElement(readProjectsFromFile(filename));
    if (!(doc == null)) {
        NodeList project = doc.getElementsByTagName(project);

        for (int i = 0; i < project.getLength(); i++) {

            HashMap<String, String> map = new HashMap<>();
            Element e = (Element) project.item(i);

            map.put(project_uuid, parser.getAttribute(e, project_uuid));

            map.put(project_company, parser.getValue(e, project_company));
            map.put(project_company_image, parser.getValue(e, project_company_image));
            map.put(project_company_street, parser.getValue(e, project_company_street));
            map.put(project_company_zip, parser.getValue(e, project_company_zip));
            map.put(project_company_city, parser.getValue(e, project_company_city));
            //map.put(project_company_country, parser.getValue(e, project_company_country));
            projectMap.add(map);
        }
        NodeList job = doc.getElementsByTagName(job);
        for (int i = 0; i < job.getLength(); i++) {
            HashMap<String, String> map = new HashMap<>();
            Element e = (Element) job.item(i);

            map.put(job_uuid, parser.getAttribute(e, job_uuid));

            map.put(job_subject, parser.getValue(e, job_subject));
            map.put(job_description, parser.getValue(e, job_description));
            //map.put(job_typ, parser.getValue(e, job_typ));
            map.put(job_deadline, parser.getValue(e, job_deadline));
            //map.put(job_task_count_all, parser.getValue(e, job_task_count_all));
            //map.put(job_task_count_open, parser.getValue(e, job_task_count_open));
            jobMap.add(map);
        }
    }
}

我必须在哪里使用 public Document getDomElement(String xml) { Document doc; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder db = dbf.newDocumentBuilder(); InputSource is = new InputSource(); is.setCharacterStream(new StringReader(xml)); doc = db.parse(new ByteArrayInputStream(xml.getBytes())); } catch (ParserConfigurationException e) { Log.e("Error Parser: ", e.getMessage()); return null; } catch (SAXException e) { Log.e("Error SAX: ", e.getMessage()); return null; } catch (IOException e) { Log.e("Error IO: ", e.getMessage()); return null; } return doc; } 以及该方法是什么?

1 个答案:

答案 0 :(得分:3)

doInBackground()(顾名思义)在后台线程上运行。除非您使用数据发布转轮等,否则该线程中生成的数据(特别是添加到projectMap和jobMap的HashMaps)在另一个线程中不可用。幕后AsyncTask(以及其他内容)的作用是将数据从后台线程传递到UI线程。它从doInBackground()onPostExecute()执行此操作。

您可以做的是修改AsyncTask,以便doInBackground()返回您需要的数据(而不是返回null),然后将其用作onPostExecute()中的参数。例如:

class setProjectsFilesNamesMap extends  AsyncTask<Void,Void,HashMap<String, ArrayList<String> > >{

    @Override
    protected HashMap<String, ArrayList<String>> doInBackground(Void...voids) {
        //Fülle die Maps mit Daten
        HashMap<String, ArrayList<String>> data = new HashMap<String, ArrayList<String>>();
        for (int position = 0; position < projectFileNamesMap.size(); position++) {
            String filename = projectFileNamesMap.get(position);
            ArrayList <String> jobMap = setJobMap(filename);
            ArrayList <String> projectMap = setProjectMap(filename);
            data.add("jobMap", jobMap);
            data.add("projectMap", projectMap):
        }
        return data;
    }

    @Override
    protected void onPostExecute(HashMap <String, ArrayList<String>> data){
        CustomAdapterProjects adapter = new CustomAdapterProjects(ProjectsList.context, data.get("projectMap"), data.get("jobMap"));
        setListAdapter(adapter);
    }
}

当然这意味着你需要改变setJobMap和setProjectMap来返回地图,而不仅仅是设置它们。