当前位置: 首页 > 知识库问答 >
问题:

此AsyncTask类应该是静态的,否则可能发生泄漏(匿名Android.os.AsyncTask)

汪建白
2023-03-14

我的项目中有一个AsyncTask,有一个警告,它说:

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();

共有1个答案

东方宜
2023-03-14

为了澄清ynsmtki在特定情况下的含义:您的asyncTask是在UI事件处理程序/回调方法中声明的(让我们将其命名为onSomeUIEventHandler{},但它将产生自己的线程,并携带更长的范围引用,如(1)progressDialog,(2)DataBase,(3)propertyInfo,这些引用是泄漏警告的来源。

正如其他人所指出的,这一直是一个安静的问题,直到IntelliJ在两年前部署(实际上是释放)他们的KotlinT分析器。直到最近(在AS V3.0+)中,分析器实际上提供了解决泄漏的有意义的提示,这一直是一个需要解决的难题。下面是它现在的辅助功能,它甚至通过IDE为您生成子类签名:

因此,您需要通过为它们指定getter()方法,即在扩展asyncTask类中使用的getDatabase()、getProgressDialog()和getPropertyInfo(),来执行()异步任务线程,这些方法具有上述三个类的只读副本:

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();
// ...
}

在任务的静态上下文中,getter的实例方法不能被调用的地方可能还有其他微妙之处,所以您可以使它们成为静态的,或者将它们的单例容器(如Activity或context)传递到asyncTask块中,以便在那里使用它们的getter()来通过编译器错误。

ParentContainer parent = getDialogContainer();
final ProgressDialog progressDialog = parent.getProgressDialog() // etc
 类似资料: