我得到了例外 “ * 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();
}
}
}
}
答案 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)然后publishProgress
和onProgressUpdate
时,您可以将其添加到附加到适配器的另一个List
。注意:您已尝试此操作以查看其行为。