Я разрабатываю приложение для Android 2.3.3 с сервисом. У меня есть это внутри этого сервиса для связи с основной деятельностью:
public class UDPListenerService extends Service
{
private static final String TAG = "UDPListenerService";
//private ThreadGroup myThreads = new ThreadGroup("UDPListenerServiceWorker");
private UDPListenerThread myThread;
/**
* Handler to communicate from WorkerThread to service.
*/
private Handler mServiceHandler;
// Used to receive messages from the Activity
final Messenger inMessenger = new Messenger(new IncomingHandler());
// Use to send message to the Activity
private Messenger outMessenger;
class IncomingHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
}
}
/**
* Target we publish for clients to send messages to Incoming Handler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
[ ... ]
}
И вот, final Messenger mMessenger = new Messenger(new IncomingHandler());
я получаю следующее предупреждение Lint:
This Handler class should be static or leaks might occur: IncomingHandler
Что это означает?
Ответы:
Если
IncomingHandler
класс не является статическим, он будет иметь ссылку на вашService
объект.Handler
Все объекты одной и той же цепочки имеют общий объект Looper, в который они отправляют сообщения и читают из них.Поскольку сообщения содержат цель
Handler
, пока в очереди сообщений есть сообщения с целевым обработчиком, этот обработчик не может быть подвергнут сборке мусора. Если обработчик не статичен, выService
илиActivity
не можете собрать мусор, даже после уничтожения.Это может привести к утечкам памяти, по крайней мере, в течение некоторого времени, пока сообщения остаются в очереди. Это не большая проблема, если вы не публикуете сообщения с задержкой.
Вы можете сделать
IncomingHandler
статический и иметьWeakReference
к вашим услугам:Смотрите этот пост от Romain Guy для дальнейшего использования
источник
get()
вернет ноль, когда указанный объект был gc-ed. В этом случае, когда сервис мертв.Как уже упоминали другие, предупреждение Lint связано с потенциальной утечкой памяти. Вы можете избежать предупреждения Lint, передавая
Handler.Callback
при конструированииHandler
(то есть, вы не создаете подклассHandler
и не существуетHandler
нестатического внутреннего класса):Насколько я понимаю, это не избежит потенциальной утечки памяти.
Message
Объекты содержат ссылку наmIncomingHandler
объект, который содержит ссылку наHandler.Callback
объект, который содержит ссылку наService
объект. Пока вLooper
очереди сообщений есть сообщения,Service
GC не будет. Тем не менее, это не будет серьезной проблемой, если у вас нет сообщений с длительной задержкой в очереди сообщений.источник
Вот общий пример использования слабой ссылки и класса статического обработчика для решения проблемы (как рекомендуется в документации Lint):
источник
Myclass
должен быть объявлен какpublic Handler getHandler()
вместоpublic void
Этот способ хорошо сработал для меня, поддерживает чистоту кода, сохраняя место обработки сообщения в его собственном внутреннем классе.
Обработчик, который вы хотите использовать
Внутренний класс
источник
С помощью ответа @ Sogger я создал общий обработчик:
Интерфейс:
Я использую это следующим образом. Но я не уверен на 100%, если это утечка. Может быть, кто-то мог бы прокомментировать это:
источник
Я не уверен, но вы можете попробовать инициализировать обработчик для обнуления в onDestroy ()
источник
Я запутался. В приведенном мной примере полностью исключено статическое свойство и используется поток пользовательского интерфейса:
Что мне нравится в этом решении, так это то, что нет проблем с попыткой смешать переменные класса и метода.
источник