Возможная альтернатива статическим внутренним классам, чтобы предотвратить утечку памяти в android / java?

В последнее время я занимаюсь исследованием утечек памяти в java / android и почти везде, где говорится, что вместо анонимных классов я должен использовать статические внутренние классы со слабыми ссылками.
Поэтому в моем приложении для Android я начал делать это, но очень быстро устал от этого, потому что у него много шаблонов кода … Я думаю, есть альтернативное решение, которое я бы предпочел использовать, но я не знаю, что это Действительной альтернативой статическим внутренним классам в плане предотвращения утечек памяти. Как я уже говорил, я не видел, чтобы это решение предлагалось где-нибудь еще (все говорят, что нужно использовать статические внутренние классы), поэтому я не уверен, что моя альтернатива будет работать.

Плохо используйте простой пример из моего приложения:
У меня есть класс под названием WebClient, который обрабатывает асинхронные веб-запросы, и он принимает интерфейс iCallback, который возвращает ответ от сервера на вызывающего, и в моей деятельности, когда я получаю этот обратный вызов, мне нужно отклонить диалог и, возможно, выполнить некоторую активность (Например, trigger onBackPressed () и setResult ()).
Поэтому вот мой статический внутренний класс, который я создал:

private static class CallBack implements WebClient.ICallback { private WeakReference<ProgressDialog> mProgDiag; private WeakReference<BaseActivity> mActivity; public CallBack(BaseActivity activity, ProgressDialog progDiag) { this.mProgDiag = new WeakReference<>(progDiag); this.mActivity = new WeakReference<>(activity); } @Override public void onCallback(String data) { String responseAsString = Utils.extractStringFromResponse(...); final BaseActivity parentActivity = mActivity.get(); ProgressDialog dialog = mProgDiag.get(); if(dialog != null) { dialog.dismiss(); } if (responseAsString == null) { if(parentActivity != null) { Utils.makeServerErrorDialog(parentActivity, new iDialogButtonClickedListener() { @Override public void onDialogButtonClicked() { parentActivity.onBackPressed(); } }); } return; } //everything is ok if (responseAsString.equals("1")) { if(parentActivity != null) { Intent result = new Intent(); result.putExtra(...); parentActivity.setResult(Activity.RESULT_OK, result); } } else { Utils.reportErrorToServer(...); if(parentActivity != null) { parentActivity.setResult(Activity.RESULT_CANCELED); } } if(parentActivity != null) { parentActivity.onBackPressed(); } } } 

Поэтому для каждой переменной, которая мне нужна в этом статическом внутреннем классе, я должен создать новую слабую ссылку, а затем извлечь объект сам, а затем каждый раз, когда я хочу получить к нему доступ, мне нужно проверить, является ли оно нулевым … это похоже на много Кода для меня.

И вот моя предложенная альтернатива:

 public abstract class BaseActivity extends AppCompatActivity implements WebClient.ICallback { private static final String TAG = "BaseActivity"; WebClient.ICallback mCallBack; ProgressDialog mProgDiag; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(...); mCallBack = this; //some code to invoke a server request on button click //and passing mCallBack to the request } @Override public void onCallback(String data) { String responseAsString = Utils.extractStringFromResponse(...); mProgDiag.dismiss(); if (responseAsString == null) { Utils.makeServerErrorDialog(this, new iDialogButtonClickedListener() { @Override public void onDialogButtonClicked() { onBackPressed(); } }); return; } //everything is ok if (responseAsString.equals("1")) { Intent result = new Intent(); result.putExtra(...); setResult(Activity.RESULT_OK, result); } else { Utils.reportErrorToServer(...); setResult(Activity.RESULT_CANCELED); } onBackPressed(); } @Override protected void onPause() { mCallBack = null; super.onPause(); } @Override protected void onResume() { super.onResume(); mCallBack = this; } } 

Для меня это кажется намного более чистым: не создавать и извлекать экземпляры слабых ссылок для каждой переменной, к которой мне нужен доступ, я могу напрямую вызывать методы активности (например, onBackPressed ()) и не проверять значение null везде.
Единственное место, где я должен был бы проверять значение null, находится внутри класса WebClient перед вызовом метода callBack.

Поэтому мой вопрос заключается в том, достигает ли такой подход такого же результата с точки зрения предотвращения утечек памяти? Это «достойная» альтернатива статическим внутренним классам?

Solutions Collecting From Web of "Возможная альтернатива статическим внутренним классам, чтобы предотвратить утечку памяти в android / java?"

К сожалению, ваш подход не работает. Внедряя WebClient.ICallback в своей деятельности, а не в внутренний класс, вы не избавляетесь от утечки. Утечка происходит не потому, что ссылки на активность и диалог неявны в анонимном классе или в лямбда или в нестационарном экземпляре внутреннего класса; Это происходит, когда WebClient сохраняет эту ссылку, пока активность не исчезла (она не разрушена, потому что есть сильная ссылка на нее).

Специальный mCallBack, который вы установили равным null, когда действие приостановлено, ничего не получает. Также вы можете просто передать экземпляр своей деятельности в WebClient. Теперь есть сильная ссылка на вашу деятельность, которой управляет кто-то (асинхронные обработчики WebClient), который не находится под вашим контролем. Если вам не повезло, обработчик async застрянет где-нибудь и никогда не выпустит эту ссылку.

Прочтите это подробное объяснение .

Обратите внимание, что сам WebView может вызвать утечку памяти , если не будут предприняты специальные меры!