我正在尝试开发一款能够列出所有应用及其缓存的Android应用。
但是我遇到了一个问题,即每当我点击生成的列表时,我都会因为关闭而关闭
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.
所以我试图将我的AsyncTask代码转换为Thread Hadler,任何人都可以帮我解决这个问题。这是我的代码
public class Messages extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
msgList = (ListView) findViewById(R.id.MessageList);
applicationCacheSize = new ArrayList<Long>();
applicationPackageName = new ArrayList<String>();
applicationName = new ArrayList<String>();
cacheApplicationName = new ArrayList<String>();
details = new ArrayList<MessageDetails>();
new AsyncTask<Void, Void, Void>() {
@Override
protected void onPreExecute() {
pd = ProgressDialog.show(Messages.this, "Loading..",
"Please Wait", true, false);
}// End of onPreExecute method
@Override
protected Void doInBackground(Void... params) {
for (ApplicationInfo packageInfo : packages)
{
try
{
Context mContext = createPackageContext(packageInfo.packageName, CONTEXT_IGNORE_SECURITY);
PackageManager pm = mContext.getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo( mContext.getPackageName(), 0);
} catch (final NameNotFoundException e) {
ai = null;
}
final String applicationName = (String) (ai != null ? pm.getApplicationLabel(ai) : "(unknown)");
appNames.add(applicationName);
appPackageName.add(packageInfo.packageName);
appCache.add(mContext.getCacheDir());
}
catch (NameNotFoundException e)
{
e.printStackTrace();
}
}
for(int i=0; i<appCache.size(); i++)
{
try {
final PackageManager pm = getPackageManager();
Method getPackageSizeInfo;
getPackageSizeInfo = pm.getClass().getMethod(
"getPackageSizeInfo", String.class, IPackageStatsObserver.class);
getPackageSizeInfo.invoke(pm, appPackageName.get(i), new IPackageStatsObserver.Stub() {
@Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
throws RemoteException {
final String title;
ApplicationInfo applicationInfo;
try {
applicationInfo = pm.getApplicationInfo(pStats.packageName, 0);
title = (String)((applicationInfo != null) ? packageManager.getApplicationLabel(applicationInfo) : "???");
MessageDetails Detail;
Detail = new MessageDetails();
Detail.setIcon(getPackageManager().getApplicationIcon( pStats.packageName ));
Detail.setName(title);
Detail.setSub("Cache Size -> "+(((pStats.cacheSize/1024) > 0)?(pStats.cacheSize/1024):"No Cache"));
details.add(Detail);
if((pStats.cacheSize) != 0 )
{
cacheApplicationName.add(title);
}
} catch (final NameNotFoundException e) {}
}
});
}
catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}// End of doInBackground method
@Override
protected void onPostExecute(Void result) {
CustomAdapter adapter = new CustomAdapter(details, Messages.this);
msgList.setAdapter(adapter);
pd.dismiss();
}// End of onPostExecute method
}.execute((Void[]) null);
}
}
提前致谢。
答案 0 :(得分:0)
首先,不要使用detail = new Asyntasck
。在下面创建Asynctask类,只需使用:
AsynTask myTask = new AsynTask();
myTask.execute();
然后,您的适配器实际上是从后台线程(asynctask)修改的,与建议的异常完全相同。解决方案是将其移动到UI线程或简单地使用runOnUiThread()包装它:
... ...
runOnUiThread(new Runnable() {
public void run() {
details.add(result) //use a foreach here
CustomAdapter adapter = new CustomAdapter(details, Messages.this);
adapter.notifyDataSetChanged();
msgList.setAdapter(adapter);
pd.dismiss();
}
}); // end of runOnUiThread
... ...