Предупреждение: не размещайте классы контекста Android в статических полях; Это утечка памяти (а также прерывает Instant Run)

Android Studio:

Не размещайте классы контекста Android в статических полях; Это утечка памяти (а также прерывает Instant Run)

Итак, 2 вопроса:

# 1 Как вы вызываете startService из статического метода без статической переменной для контекста?
# 2 Как вы отправляете localBroadcast из статического метода (то же самое)?

Примеры:

 public static void log(int iLogLevel, String sRequest, String sData) { if(iLogLevel > 0) { Intent intent = new Intent(mContext, LogService.class); intent.putExtra("UPDATE_MAIN_ACTIVITY_VIEW", "UPDATE_MAIN_ACTIVITY_VIEW"); mContext.startService(intent); } } 

или

  Intent intent = new Intent(MAIN_ACTIVITY_RECEIVER_INTENT); intent.putExtra(MAIN_ACTIVITY_REQUEST_FOR_UPDATE, sRequest)); intent.putExtra(MAIN_ACTIVITY_DATA_FOR_VIEW, sData); intent.putExtra(MAIN_ACTIVITY_LOG_LEVEL, iLogLevel); LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent); 

Каким будет правильный способ сделать это без использования mContext ?

ПРИМЕЧАНИЕ. Я думаю, что мой главный вопрос заключается в том, как передать контекст классу, из которого вызывается метод вызова.

Solutions Collecting From Web of "Предупреждение: не размещайте классы контекста Android в статических полях; Это утечка памяти (а также прерывает Instant Run)"

Просто передайте его как параметр вашему методу. Нет смысла создавать статический экземпляр Context исключительно для цели Intent .

Вот как должен выглядеть ваш метод:

 public static void log(int iLogLevel, String sRequest, String sData, Context ctx) { if(iLogLevel > 0) { Intent intent = new Intent(ctx, LogService.class); intent1.putExtra("UPDATE_MAIN_ACTIVITY_VIEW", "UPDATE_MAIN_ACTIVITY_VIEW"); ctx.startService(intent); } } 

Обновление из комментариев по вопросу: каскадируйте контекст из инициирующего действия (через параметры конструктора или параметры метода) вплоть до нужной вам точки.

Просто убедитесь, что вы передаете context.getApplicationContext () или вызываете getApplicationContext () в любом контексте, который передается через методы / конструктор в ваш singleton, если вы решили сохранить его в любом поле участника.

Пример идиотского доказательства (даже если кто-то перейдет в действие, он захватит контекст приложения и будет использовать его для создания экземпляра сингла):

 public static synchronized RestClient getInstance(Context context) { if (mInstance == null) { mInstance = new RestClient(context.getApplicationContext()); } return mInstance; } 

GetApplicationContext () в соответствии с документами: «Вернуть контекст единого глобального объекта приложения текущего процесса».

Это означает, что контекст, возвращаемый функцией getApplicationContext (), будет работать через весь процесс, и, следовательно, не имеет значения, сохраняете ли вы статическую ссылку на него где угодно, поскольку она всегда будет присутствовать во время выполнения вашего приложения (и переживет любые объекты / Singletons, созданных им).

Сравните это с контекстом внутри представлений / видов деятельности, содержащих большие объемы данных, если вы протекаете из контекста, содержащегося в активности, система не сможет освободить этот ресурс, который явно не подходит.

Ссылка на деятельность по ее контексту должна жить в том же жизненном цикле, что и сама деятельность, иначе она будет удерживать контекстную заложницу, вызывающую утечку памяти (что является причиной предупреждения линта).

EDIT: Для парня, который избивает пример из приведенных выше документов, в коде есть только часть комментария о том, о чем я только что писал:

  // getApplicationContext() is key, it keeps you from leaking the // Activity or BroadcastReceiver if someone passes one in. 

Просто предупреждение. Не беспокойтесь. Но если вы хотите использовать контекст приложения, вы можете сохранить его в классе «singleton», который используется для сохранения всего одноэлементного класса в вашем проекте.

В вашем случае это не имеет смысла иметь это как статическое поле, но я не думаю, что это плохо во всех случаях. Если вы теперь делаете, вы можете иметь статическое поле, имеющее контекст, и null позже. Я создаю статический экземпляр для моего основного класса модели, в котором есть контекст внутри, его контекст приложения, а не контекст активности, а также у меня есть статическое поле экземпляра класса, содержащего Activity, в котором я null in on destroy. Я не вижу, что у меня утечка памяти. Поэтому, если какой-нибудь умный парень думает, что я ошибаюсь, не стесняйтесь комментировать …

Также Instant Run работает здесь отлично …