Listview和改编版正在抛出“java.lang.IllegalStateException:”

时间:2011-12-02 19:29:36

标签: android

我得到了例外 “ * java.lang.IllegalStateException:适配器的内容已更改,但ListView未收到通知。请确保未从后台线程修改适配器的cont * ent,但只能从UI线程。

My Code有两个线程,一个用于SAX解析,另一个是线程扩展asynctask类

每次更改ArrayList内容时检查内容的

..并在onProgressUpdate()中调用adapter.notifyDatasetChange()方法。

但是我希望输出在解析器进行解析时,应该是受尊重的元素 添加到列表视图....请帮助我guyzzz ..... 我的代码是......

public class SearchProperty扩展了Activity {

boolean isDone;
List<Property> properties = new ArrayList<Property>();
ListView list;
ArrayAdapter<Property> adapter;
InputStream in;
ProgressDialog dialog;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.newlay);

    list = (ListView) findViewById(R.id.mylistview);
    list.setPadding(0, 20, 0, 20);
    dialog = new ProgressDialog(this);
    dialog.setCancelable(true);
    dialog.setMessage("Please Wait...");
    dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

    adapter = new ArrayAdapter<Property>(this,
            android.R.layout.simple_list_item_1, properties);
    list.setAdapter(adapter);

    list.setOnItemClickListener( new OnItemClickListener() 
    {

        public void onItemClick(AdapterView<?> parent, View view, int pos,
                long id) {
            Toast.makeText( SearchProperty.this , "Please Wait... Application is under progress..." , Toast.LENGTH_SHORT).show();
        }


    });

    FileParserTask task = new FileParserTask();

    Thread thread = new Thread(task);
    thread.start();

    SetTimeoutTask task11 = new SetTimeoutTask();
    task11.execute();



    System.out.println("I m done!!");
}

**// This thread is checking arraylist time to time after 50 ms and call on progressUpdate**
private class SetTimeoutTask extends AsyncTask<String, Void, String> {
    @Override

    protected void onPreExecute() { 

        dialog.show();

    };
    protected String doInBackground(String... urls) 
    {
    //  Log.e("...","in do InBackground.....");
        try {
            for (;;) {
                if (isDone)
                    break;
                publishProgress();
                Thread.sleep(50);

            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        dialog.dismiss();


    }
    @Override
    protected void onProgressUpdate(Void... values) 
    {

        //Log.e("...","in onprogressupdate.....");
        super.onProgressUpdate(values);
        if(list.getAdapter()!=null)
        adapter.notifyDataSetChanged();
    }

}


    **// this thread is doing parsing of xml file in background....**

class FileParserTask implements Runnable {

    @Override
    public void run() {


        try {
            in = getAssets().open("property.xml");
            PropertyHandler myhandler = new PropertyHandler(properties);
            XMLReader xmlReader = SAXParserFactory.newInstance()
                    .newSAXParser().getXMLReader();
            xmlReader.setContentHandler(myhandler);
            xmlReader.parse(new InputSource(in));
            isDone = true;
            System.out.println("Done!!!");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // EstateParser.parse(in,properties,adapter);
        catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FactoryConfigurationError e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

}

2 个答案:

答案 0 :(得分:0)

好的,我猜你的SAX解析器的处理程序是直接更新支持ListView的数组?

那我认为是问题所在。您需要为SAX解析器提供单独的列表,然后在onProgressUpdate调用期间将其传输到支持ListView的List,因为它位于UI线程中。

答案 1 :(得分:0)

从上面获取一些代码片段:

List<Property> properties = new ArrayList<Property>();

然后你有

adapter = new ArrayAdapter<Property>(this,
        android.R.layout.simple_list_item_1, properties);
list.setAdapter(adapter);

您描述代码的方式看起来像是从properties添加到FileParserTask(尽管我在上面的代码中看不到)。如果我是对的并且您要在properties中添加FileParserTask,那么您很可能会收到此错误。原因是,您的下划线properties在非UI线程中被修改,这意味着您的ArrayAdapter也在非UI线程中被修改。

这导致状态不一致,并且您得到上述异常。尝试通过轻微的设计更改将解析器代码移动到AsyncTask

一个选项是在单独的列表中加载所有属性,然后在ListView中的onPostExecute上创建和设置新适配器。如果您不想在添加内容时看到更新的ListView但仍希望查看进度状态,则此功能将有效。

第二个选项是,创建临时列表以在解析时存储少量属性。当列表达到某个限制(比如5)然后publishProgressonProgressUpdate时,您可以将其添加到附加到适配器的另一个List。注意:您已尝试此操作以查看其行为。