【问题标题】:How do I put AsyncTask code to Thread Handler如何将 AsyncTask 代码放入线程处理程序
【发布时间】:2013-07-10 08:44:28
【问题描述】:

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

提前致谢。

【问题讨论】:

  • 在 doInBackground 执行期间使用 publishProgress 和 onProgressUpdate 发布到 ui 线程。
  • @njzk2 实际上我试过了,但对我不起作用,可能是我在错误的地方用错误的参数编码,你能否将答案发布为我的代码的编辑版本,请不要介意
  • 你为什么要对类进行内联编码?把它移出来,给它起个名字,然后在应用程序中执行它..这样会更容易理解..
  • @Miro Markarian 任何方式的代码都应该可以正常工作,但on click 我收到了Force Close
  • 你能发布实际的堆栈跟踪吗?

标签: android android-asynctask android-handler


【解决方案1】:

首先,不要使用detail = new Asyntasck。在下面创建 Asynctask 类并使用:

AsynTask myTask = new AsynTask();
myTask.execute();

然后您的适配器实际上是从后台线程(异步任务)修改的,正如异常所建议的那样。解决方案是将其移动到 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

... ...

【讨论】:

  • 我的错误,他分析了他的数组。
  • @marshallino16 在添加到details 列表时如何声明和初始化result
  • @marshallino16 你不能像AsynTask myTask = new AsynTask();一样初始化AsyncTask
  • 您的 asynctask 是一个类,因此您可以像这样初始化一个对象,然后执行:mytask.execute(); 看看:stackoverflow.com/questions/9671546/asynctask-android-example
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-01
  • 1970-01-01
  • 2014-07-09
  • 2015-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多