0

我正在尝试开发一个可以列出所有应用程序及其缓存的 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);
}
}

提前致谢。

4

1 回答 1

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

... ...
于 2013-07-10T09:49:29.870 回答