android.view.WindowLeaked for tablet asynctask,同时尝试设置纵向方向

时间:2014-09-18 18:36:26

标签: java android android-asynctask progressdialog

我的活动仅以纵向显示,而在我的平板电脑中则显示以下内容:

 android.view.WindowLeaked: Activity com.spicycurryman.getdisciplined10.app.InstalledAppActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{53210b88 V.E..... R.....ID 0,0-1520,192} that was originally added here
            at android.view.ViewRootImpl.<init>(ViewRootImpl.java:354)
            at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:216)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
            at android.app.Dialog.show(Dialog.java:281)
            at com.spicycurryman.getdisciplined10.app.InstalledAppActivity$LoadApplications.onPreExecute(InstalledAppActivity.java:306)
            at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
            at android.os.AsyncTask.execute(AsyncTask.java:534)
            at com.spicycurryman.getdisciplined10.app.InstalledAppActivity.onCreate(InstalledAppActivity.java:105)
            at android.app.Activity.performCreate(Activity.java:5104)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
            at android.app.ActivityThread.access$600(ActivityThread.java:141)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5041)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)

我正在使用AsyncTask在手机上加载已安装应用的列表视图并使用progressdialog。

我研究过这个问题:

Progress dialog and AsyncTask error

android.view.WindowLeaked exception

Android Error: Window Leaked in AsyncTask

我能够生成这个代码,以便整个应用程序不会崩溃和刻录,但仍然会抛出异常,并且按钮单击后活动屏幕有点不稳定,整个转换不是很顺利。

 @Override
        protected void onPostExecute(Void result) {

            apkList.setAdapter(new ApkAdapter(InstalledAppActivity.this, packageList1, packageManager));

            try {
                if ((this.pDialog != null) && this.pDialog.isShowing()) {
                    this.pDialog.dismiss();
                }
            } catch (final IllegalArgumentException e) {
                // Handle or log or ignore
            } catch (final Exception e) {
                // Handle or log or ignore
            } finally {
                this.pDialog = null;
            }


            super.onPostExecute(result);
        }

取消进度对话框或调用finish()并没有真正解决问题...

我该如何解决这个问题?

以下是大部分AsyncTask代码:

    private class LoadApplications extends AsyncTask<Void, Void, Void> {


        private ProgressDialog pDialog;
        List<PackageInfo> packageList1 = new ArrayList<PackageInfo>();

        public LoadApplications(Context context){
            Context mContext = context;
        }

        @Override
        protected Void doInBackground(Void... params) {

            List<PackageInfo> packageList = packageManager
                    .getInstalledPackages(PackageManager.GET_PERMISSIONS);

            List<PackageInfo> packageList2 = packageManager
                    .getInstalledPackages(PackageManager.GET_PERMISSIONS);

            for(PackageInfo pi : packageList) {

                boolean b = isSystemPackage(pi);
                boolean c = isSystemPackage1(pi);
                boolean d = isSystemPackage2(pi);


                if ((!b || !c ) && d ){
                    packageList1.add(pi);
                }

            }

            //here you got email and message apps in the 

            for(PackageInfo pi : packageList) {

                boolean b = isSystemPackage3(pi);
                boolean c = isSystemPackage4(pi);


                if (b || c){
                    packageList1.add(pi);
                }

            }






            //sort by application name

            final PackageItemInfo.DisplayNameComparator comparator = new PackageItemInfo.DisplayNameComparator(packageManager);

            Collections.sort(packageList1, new Comparator<PackageInfo>() {
                @Override
                public int compare(PackageInfo lhs, PackageInfo rhs) {
                    return comparator.compare(lhs.applicationInfo, rhs.applicationInfo);
                }
            });

            return null;
        }
        @Override
        protected void onCancelled() {
            super.onCancelled();
        }

        @Override
        protected void onPreExecute() {
            pDialog = new ProgressDialog(InstalledAppActivity.this);
            pDialog.setMessage("Loading your apps...");
            pDialog.show();

        }
        //Inefficient patch to prevent Window Manager error


        @Override
        protected void onPostExecute(Void result) {

            apkList.setAdapter(new ApkAdapter(InstalledAppActivity.this, packageList1, packageManager));

            try {
                if ((this.pDialog != null) && this.pDialog.isShowing()) {
                    this.pDialog.dismiss();
                }
            } catch (final IllegalArgumentException e) {
                // Handle or log or ignore
            } catch (final Exception e) {
                // Handle or log or ignore
            } finally {
                this.pDialog = null;
            }


            super.onPostExecute(result);
        }

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

2 个答案:

答案 0 :(得分:0)

试试这个:

@Override
    public Object onRetainNonConfigurationInstance() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog = null;
        }
        if (asynTask!= null) {
            asynTask.detach();
        }
        return ayncTask;
    }

答案 1 :(得分:0)

在您的活动中声明一个非静态的内部AsyncTask不是一个好主意,因为它包含对活动的引用,这可能是泄漏的一个因素。但是,各种配置更改可能导致操作系统破坏并重新创建活动。有很多解决方案,Rustam的anser就是一个例子。

但是,我更喜欢使用AsyncTaskLoader或使用某种异步回调,比如广播。异步回调将AsyncTask与Activity分离。