这个类的AsyncTask应该是静态的或可能发生泄漏(匿名android.os.AsyncTask)

问题描述 投票:1回答:2

我有一个的AsyncTask在我的项目,有是说一个警告:

这个类的AsyncTask应该是静态的或泄漏可能发生(匿名android.os.AsyncTask)少...(按Ctrl + F1)静态字段会泄漏上下文。非静态内部类都有自己的外部类的隐式引用。如果该外部类是例如片段或活性,则该引用意味着,长期运行的处理程序/装载器/任务将保持到其阻止它得到垃圾收集活性的参考。同样,这些较长的运行实例的活动和片段直接场引用可能导致泄漏。视图模型类不应该指向的意见或非应用程序环境。

这里是我的代码,包含此警报:

ProgressDialog progressDialog;
     AsyncTask<String,Void,Boolean> asyncTask = new AsyncTask<String, Void, Boolean>() {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog.setTitle("بارگذاری");
            progressDialog.setMessage("در حال دریافت اطلاعات از پایگاه داده..");
            progressDialog.setCancelable(false);
            progressDialog.show();
        }


        @Override
        protected Boolean doInBackground(String... strings) {
            Cursor cursor = DataBase.getinfos(page,limit);

            if (cursor.isAfterLast()){
                return false;
            }else {

                for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
                    PropertyInfo propertyInfo = new PropertyInfo();
                    propertyInfo.setId(cursor.getInt(0));
                    propertyInfo.setAddress(cursor.getString(1));
                    propertyInfo.setDetails(cursor.getString(2));
                    propertyInfo.setOptions(cursor.getString(3));
                    propertyInfo.setMortgage_cost(cursor.getLong(4));
                    propertyInfo.setRent_cost(cursor.getLong(5));
                    propertyInfo.setOwner_name(cursor.getString(6));
                    propertyInfo.setUnits_per_floor(cursor.getInt(7));
                    propertyInfo.setCurrent_floor(cursor.getInt(8));
                    propertyInfo.setFloors_count(cursor.getInt(9));
                    propertyInfo.setRoom_count(cursor.getString(10));
                    propertyInfo.setOwner_phone(cursor.getString(11));
                    propertyInfo.setDocument_type(cursor.getString(12));
                    propertyInfo.setRequest_type(cursor.getString(13));
                    propertyInfo.setProperty_type(cursor.getString(14));
                    propertyInfo.setCost(cursor.getLong(15));
                    propertyInfo.setArea(cursor.getInt(16));
                    propertyInfo.setHouse_type(cursor.getString(17));
                    propertyInfo.setLocation(cursor.getString(19));
                    propertyInfo.setNoeMorajeKonande(cursor.getString(18));
                    propertyInfo.setShomareSafhe(cursor.getString(20));
                    propertyInfo.setDate(cursor.getString(21));
                    arrayList.add(propertyInfo);
                    lastRecivedDataSize++;
                }
                return true;
            }
        }


        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            loading = aBoolean;
            if (arrayList.isEmpty()) {
                setContentView(R.layout.no_result);
            } else {
                mAdapter = new RecyclerInfoAdapter(arrayList, ShowAllDataActivity.this);
                mAdapter.notifyDataSetChanged();
                recyclerView.setAdapter(mAdapter);
                recyclerView.scrollToPosition(pastVisiblesItems + visibleItemCount - 1);
                page++;


            }
            progressDialog.dismiss();

        }
    };

    asyncTask.execute();

任何人都知道这个问题的?

android android-asynctask
2个回答
0
投票

创建实现的AsyncTask一个单独的类,然后在你的活动实例化,并运行执行方法。


1
投票

只是为了澄清什么ynsmtki意味着您的具体情况:您的AsyncTask是UI事件处理器/回调方法(内声明允许其命名为onSomeUIEventHandler {},但它应酿出自己的线程与它承载更长的范围内引用,如(1) progressDialog,(2)数据库,(3)的PropertyInfo,这是泄漏警告的来源。

正如其他人指出,这一直是一个安静的问题,直到部署的IntelliJ(如虎添翼,实际上)他们KotlinT分析追溯到两年前。它已经解决直到最近(在AS V3.0 +),其中分析仪实际上是在解决渗漏提供有意义的提示一个谜。下面是现在与协助,它甚至可以通过IDE生成子签名您:

所以,你需要通过指定的getter()为他们的方法来执行()与上述三个只读副本是异步任务的线程,即getDatabase(),getProgressDialog(),并为getPropertyInfo(),你在扩展的AsyncTask类中使用这样:

static class HandleDBaseAsyncTask extends AsyncTask<Parameterized.Parameters,Process, Result>{
final PropertyInfo propertyInfo = getPropertyInfo();
final YourDatabaseClass Database = getDatabase();
final ProgressDialog progressDialog = getProgressDialog();
// Then finish off with your original
onPreExecute() {...}
doInBackground(){...}
onPostExecute(){...}
}

然后回到原来的回调对话框泄密:

ProgressDialog progressDialog;
ProgressDialog getProgressDialog(){ return progressDialog;}
// and the same for other leakers

onSomeUIEventHandler{
HandleDBaseAsyncTask handleDBTask = new HandleDBaseAsyncTask();
handleDBTask.execute();
// ...
}

可能还有其他的微妙之处照顾那里的干将的实例方法不能在任务的静态上下文中调用,所以你会使其静态或在他们的单容器传递(如活动或上下文)到您的AsyncTask块使用他们的getter ()那里得到过去的编译器错误。

ParentContainer parent = getDialogContainer();
final ProgressDialog progressDialog = parent.getProgressDialog() // etc
© www.soinside.com 2019 - 2024. All rights reserved.