Uma introdução à gestão de memória e fugas de memória no Android

Vale a pena ter em mente que embora esta ferramenta possa ser muito útil para encontrar referências a uma suspeita de fuga, pode ser bastante difícil e complexo de usar para encontrar fugas desconhecidas e requer um pouco de análise. Dizendo que, se você dominar – é uma ótima ferramenta para ter debaixo do cinto!

LeakCanary

Image from LeakCanary

Outra maneira de encontrar vazamentos de memória é usando o Leak Canary, uma biblioteca criada pela Square que ajuda você a detectar vazamentos de memória. Ela funciona através de uma classe ObjectWatcher que contém referências fracas a objetos destruídos na pilha. Se a referência não for limpa nos cinco segundos seguintes e o Garbage Collector tiver sido executado, o objeto é considerado retido e registra isso como um vazamento de memória potencial no logcat. Muito inteligente, huh?

Para começar, simplesmente adicione a biblioteca dentro de suas dependências ao seu arquivo build.gradle, sincronize e compile.

>

Adicionar a biblioteca LeakCanary

Assim que você iniciar a aplicação, você pode ver a saída do LeakCanary no logcat enquanto ele observa os instantes e retém os objetos. Para acionar um vazamento, adicionei algumas novas tarefas em meu aplicativo TaskManager. Pouco tempo depois, recebi esta notificação do LeakCanary que indica um vazamento potencial!

Clique simplesmente na notificação para “dump heap” para investigar o vazamento potencial e este diálogo será exibido na aplicação.

>

LeakCanary está investigando as fugas ..

Leak Canary então analisa a pilha através da localização dos objetos retidos e encontra o traço de fuga que é um caminho de referências para cada objeto retido. Uma vez feito, uma notificação será exibida resumindo o número de objetos retidos e vazamentos.

Parece que encontrou o nosso vazamento! Se clicarmos nele, veremos o vestígio completo da fuga:

Está a dizer-nos que o TaskActivity está a vazar e as referências sublinhadas mostram o vestígio, está a vazar de mContext em SingletonExample – parece-me familiar! Agora sabemos como encontrar um vazamento usando o LeakCanary. 😃

Anular fugas de memória

Então, agora que encontramos a fuga de memória, como podemos evitá-las no futuro? Abaixo estão algumas das causas e padrões mais comuns.

Foto por Bogomil Mihaylov em Unsplash

Receptores de radiodifusão

Receptores de radiodifusão podem ser usados para ouvir eventos ou intenções de transmissão em todo o sistema que indicam informações do dispositivo, tais como bateria fraca, A data e a conectividade muda – por exemplo, o modo de avião foi desligado. Ao usá-los, precisamos lembrar de cancelar o registro dos receptores de transmissão, caso contrário, inevitavelmente manteremos uma referência à atividade.

Como evitá-la: Tudo que você precisa fazer é chamar unregister() no seu receptor de broadcast em onStop() na sua atividade.

Este padrão também é encontrado para asyncTask, TimerTask e threads que precisam ser cancelados em onDestroy() para evitar um vazamento.

Contexto para a classe Singleton

Por vezes precisamos passar em contexto de uma atividade para uma classe Singleton. Um exemplo disso seria uma classe utils onde precisamos acessar recursos, serviços ou arquivos internos. No entanto, passar em contexto significa que inevitavelmente nos agarramos a uma referência à atividade.

Como evitá-la: Ao invés de passar em this de uma atividade, podemos passar em contexto de aplicação se ela estiver disponível (se você quiser aprender mais sobre quando usar qual contexto, eu achei este artigo realmente útil!). Uma solução alternativa é garantir que o contexto Singleton seja nulo dentro da actividade onDestroy() método.

Referências estáticas

Referenciar uma vista ou uma actividade como estática significa que a referência à actividade não será recolhida. Isto deve ser evitado a qualquer momento.

Como evitá-lo: Se você por algum motivo tiver que fazê-lo, você pode garantir que ele seja destruído, definindo-o como nulo em onDestroy().

Referências a classes internas

As classes internas frequentemente causam vazamentos, mantendo uma referência implícita à classe externa. Isto acontece se a variável de classe é declarada como estática ou se a própria classe não é declarada como estática. Confuso? Sim, mas é fácil de evitar se seguirmos a regra simples abaixo.

Como evitá-la: Faça a classe interna estática para evitar manter uma referência à classe externa e nunca crie uma variável estática de uma classe interna. O mesmo se aplica às classes anônimas.

É isso! Espero que você tenha aprendido algumas coisas sobre vazamentos de memória e como evitá-los. Feliz codificação! 😄

Aqui estão alguns artigos e documentação que achei particularmente úteis quando aprendi sobre vazamentos de memória:

Deixe uma resposta

O seu endereço de email não será publicado.