Этот класс AsyncTask должен быть статическим, иначе могут возникнуть утечки (анонимный android.os.AsyncTask) - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть AsyncTask в моем проекте, и есть предупреждение, которое говорит:

Этот класс AsyncTask должен быть статическим, иначе утечки могут произойти (анонимный android.os.AsyncTask) меньше ... (Ctrl + F1) Статическое поле будет пропускать контексты.Нестатические внутренние классы имеют неявную ссылку на свой внешний класс.Если этот внешний класс является, например, Fragment или Activity, то эта ссылка означает, что долго выполняющийся обработчик / загрузчик / задача будет содержать ссылку на операцию, которая не позволяет собирать мусор.Точно так же прямые ссылки на поля на действия и фрагменты из этих более длительных экземпляров могут вызвать утечки.Классы ViewModel никогда не должны указывать на представления или контексты вне приложения.

Вот мой код, содержащий это предупреждение:

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

кто-нибудь знает проблему ??

Ответы [ 2 ]

0 голосов
/ 10 июня 2019

Просто чтобы уточнить, что означает ynsmtki в вашем конкретном случае: ваш asyncTask объявлен в методе обработчика событий / обратного вызова пользовательского интерфейса (назовите его onSomeUIEventHandler {}, но он должен порождать свой собственный поток, содержащий более длинные ссылки на области видимости, такие как(1) progressDialog, (2) DataBase, (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();
// ...
}

Могут быть другие тонкости, чтобы позаботиться о том, где экземпляры методов получателей не могут быть вызваныв статическом контексте задачи, поэтому вы должны сделать их статическими или передать их одноэлементный контейнер (например, Activity или Context) в свой блок asyncTask, чтобы использовать их getter () для выхода из ошибки компилятора.

ParentContainer parent = getDialogContainer();
final ProgressDialog progressDialog = parent.getProgressDialog() // etc
0 голосов
/ 04 февраля 2019

Создайте отдельный класс, который реализует AsyncTask, затем в своей деятельности создайте его экземпляр и запустите метод execute.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...