Предупреждение: Не размещайте классы контекста Android в статических полях; это утечка памяти (а также разрывы мгновенного запуска)
Android Studio:
не размещайте классы контекста Android в статических полях; это
утечка памяти (а также разрывы мгновенного запуска)
Итак, 2 вопроса:
#1 Как вы называете a 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?
примечание: Я думаю, что мой главный вопрос может заключаться в том, как передать контекст классу, из которого живет вызывающий метод.
5 ответов:
просто передайте его в качестве параметра в метод. Нет смысла создавать статический экземпляр
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); } }обновление из комментариев к вопросу: Каскадируйте контекст из инициирующей активности (через параметры конструктора или параметры метода) прямо до точки, в которой он вам нужен.
просто убедитесь, что вы передаете контекст.getApplicationContext() или вызов getApplicationContext () в любом контексте, который передается через методы/конструктор в ваш синглтон, если вы решили сохранить его в любом поле члена.
пример доказательства идиота (даже если кто-то передаст в действие, он захватит контекст приложения и использует его для создания экземпляра синглтона):
public static synchronized RestClient getInstance(Context context) { if (mInstance == null) { mInstance = new RestClient(context.getApplicationContext()); } return mInstance; }getApplicationContext () согласно документам: " возврат контекста единого, глобального Объект приложения текущего процесса."
это означает, что контекст, возвращаемый "getApplicationContext ()", будет жить через весь процесс, и поэтому не имеет значения, сохраняете ли вы статическую ссылку на него в любом месте, поскольку он всегда будет там во время выполнения вашего приложения (и переживет любые объекты/синглеты, созданные им).
сравнить, что в контексте внутри мнения/деятельность по проведению больших объемов данных, если вы утечка в контексте проводимых деятельность, система не сможет освободить тот ресурс, который явно не хорош.
ссылка на действие по его контексту должна жить в том же жизненном цикле, что и сама активность, иначе она будет держать контекст заложником, вызывая утечку памяти (что является причиной предупреждения lint).
EDIT: для парня, избивающего пример из документов выше, есть даже раздел комментариев в коде о том, что я только что написал о компании:
// getApplicationContext() is key, it keeps you from leaking the // Activity or BroadcastReceiver if someone passes one in.
Это просто предупреждение. Не волнуйся. Если вы хотите использовать контекст приложения, вы можете сохранить его в классе "singleton", который используется для сохранения всего класса singleton в вашем проекте.
в вашем случае это не имеет смысла иметь его в качестве статического поля, но я не думаю, что это плохо во всех случаях. Если вы сейчас что вы делаете, вы можете иметь статическое поле, которое имеет контекст и обнулить его позже. Я создаю статический экземпляр для моего основного класса модели, который имеет контекст внутри, его контекст приложения, а не контекст действия, а также у меня есть статическое поле экземпляра класса, содержащее действие, которое я обнуляю при уничтожении. Я не вижу, что у меня есть утечка памяти. Так что если какой-то умный парень думает, что я неправильно не стесняйтесь комментировать...
также мгновенный запуск работает нормально...
как правило, избегайте определения полей контекста как статических. Само предупреждение объясняет, почему: это утечка памяти. Нарушение мгновенного запуска мая не самая большая проблема на планете, хотя.
Теперь есть два сценария, где вы получите это предупреждение. Например (самый очевидный):
public static Context ctx;и тогда есть немного более сложный, где контекст завернут в класс:
public class Example{ public Context ctx; //Constructor omitted for brievety }и этот класс определяется как статика где-то:
public static Example example;и вы получите предупреждение.
само решение довольно простое: не помещайте поля контекста в статические экземпляры, будь то класс обертывания или объявление его статическим напрямую.
и решение для предупреждения просто: не размещайте поле статически. В вашем случае передайте контекст как экземпляр метода. Для классов, где выполняется несколько контекстных вызовов, используйте конструктор для передачи контекст (или деятельность) в классе.
обратите внимание, что это предупреждение, а не ошибку. Должны ли вы по какой-либо причине нужно статический контекст, вы можете это сделать. Хотя вы создаете утечку памяти, когда вы это делаете.
Comments