O aplicativo pode estar fazendo muito trabalho em seu encadeamento principal

379

Eu sou novo no ambiente SDK / API do Android. É a primeira vez que estou tentando desenhar um enredo / gráfico. Tentei executar diferentes tipos de códigos de amostra no emulador usando 3 bibliotecas gratuitas diferentes, nada está aparecendo na tela de layout. O logcat está repetindo a seguinte mensagem:

 W / Trace (1378): valor inesperado de nativeGetEnabledTags: 0
 I / Coreógrafo (1378): Ignorou 55 quadros! O aplicativo pode estar fazendo muito trabalho em seu encadeamento principal.

O problema não persistiu e o gráfico funcionou quando executei um código de amostra referente a uma cópia de avaliação de uma biblioteca licenciada.

user2038135
fonte
2
Você está desenhando seus gráficos em um segmento separado?
Areks
Obrigado pelo seu comentário, editei a pergunta para torná-la mais clara. A atividade durante a execução está mostrando que estou executando uma atividade que não possui um design ou layout => mostrando uma tela branca.
user2038135
11
@ Areks Não, não estou usando um thread separado.
user2038135
11
Eu acho que você deveria, não é recomendado para executar operações longas no thread principal, porque isso congela o aplicativo inteiro, você pode ler como usar os tópicos aqui: stackoverflow.com/questions/3391272/… Ignorar o "código a ser executado " a solicitação HTTP "e apenas execute suas operações potencialmente longas lá.
Areks
11
Por que você não tenta pesquisar, encontrará informações sobre o coreógrafo. Eu recomendo que você leia esta resposta: stackoverflow.com/questions/11266535/...
Gabriel Esteban

Respostas:

479

extraído de: UI do Android: corrigindo quadros ignorados

Quem começa a desenvolver aplicativos para Android vê esta mensagem no logcat “Coreógrafo (abc): quadros xx ignorados! O aplicativo pode estar fazendo muito trabalho em seu encadeamento principal. ” Então, o que realmente significa, por que você deveria se preocupar e como resolvê-lo.

O que isso significa é que seu código está demorando muito para processar e os quadros estão sendo ignorados por causa disso, talvez por causa de algum processamento pesado que você esteja fazendo no coração do aplicativo ou do acesso ao banco de dados ou qualquer outra coisa que faça com que o encadeamento pare por um tempo.

Aqui está uma explicação mais detalhada:

O Choreographer permite que os aplicativos se conectem ao vsync e cronometre corretamente as coisas para melhorar o desempenho.

As animações da visualização Android usam o Choreographer internamente para o mesmo objetivo: cronometrar adequadamente as animações e possivelmente melhorar o desempenho.

Como o Choreographer é informado sobre todos os eventos vsync, posso dizer se um dos Runnables transmitidos pelo Choreographer.post * apis não termina no tempo de um quadro, fazendo com que os quadros sejam ignorados.

No meu entendimento, o Coreógrafo pode detectar apenas o quadro pulando. Não tem como dizer por que isso acontece.

A mensagem "O aplicativo pode estar executando muito trabalho em seu encadeamento principal". pode ser enganoso.

source: Significado das mensagens do Choreographer no Logcat

Por que você deveria estar preocupado

Quando essa mensagem aparece no emulador do Android e o número de quadros ignorados é bastante pequeno (<100), você pode apostar com segurança se o emulador está lento - o que acontece quase sempre. Mas se o número de quadros saltados e grandes e da ordem de mais de 300, pode haver sérios problemas com seu código. Os dispositivos Android possuem uma vasta gama de hardware, diferente dos dispositivos iOS e Windows. A RAM e a CPU variam e, se você deseja um desempenho razoável e uma experiência do usuário em todos os dispositivos, precisará corrigir isso. Quando os quadros são ignorados, a interface do usuário é lenta e lenta, o que não é uma experiência do usuário desejável.

Como corrigi-lo

A correção disso requer a identificação de nós onde existe ou possivelmente pode ocorrer uma longa duração do processamento. A melhor maneira é fazer todo o processamento, não importa quão pequeno ou grande em um thread seja separado do thread principal da interface do usuário. Portanto, seja acessando o formulário de dados SQLite Database ou fazendo algumas matemáticas graves ou simplesmente classificando uma matriz - Faça isso em um thread diferente

Agora há um problema aqui: você criará um novo thread para executar essas operações e, quando executar o aplicativo, ele falhará dizendo "Somente o thread original que criou uma hierarquia de visualizações pode tocar suas visualizações". Você precisa saber que a UI no Android pode ser alterada apenas pelo thread principal ou pelo thread da UI. Qualquer outro encadeamento que tente fazer isso falha e trava com esse erro. O que você precisa fazer é criar um novo Runnable dentro do runOnUiThread e dentro desse executável, você deve executar todas as operações que envolvem a interface do usuário. Encontre um exemplo aqui .

Portanto, temos Thread e Runnable para processar dados fora do Thread principal, o que mais? Existe o AsyncTask no Android, que permite realizar processos demorados no thread da interface do usuário. Isso é mais útil quando os aplicativos são orientados a dados ou APIs da Web ou usam UIs complexas como as criadas usando o Canvas. O poder do AsyncTask é que ele permite fazer coisas em segundo plano e, assim que você terminar o processamento, poderá simplesmente executar as ações necessárias na interface do usuário sem causar nenhum efeito de atraso. Isso é possível porque o AsyncTask deriva do thread da UI da Activity - todas as operações realizadas na UI via AsyncTask são feitas em um thread diferente do thread da UI principal, sem impedimentos para a interação do usuário.

Portanto, é isso que você precisa saber para criar aplicativos Android suaves e, até onde eu sei, todo iniciante recebe essa mensagem em seu console.

Jorgesys
fonte
41
Eu só tenho um aplicativo em que, se eu clicar em um botão, a imagem de plano de fundo do botão muda e o botão não pode ser clicado. Como estou fazendo muito trabalho :(
Remian8985 6/15
11
@ Remian8985 - A alteração da imagem de plano de fundo do botão (supondo que você esteja baixando esta imagem) deve ser feita em um AsyncTask - que é para executar a operação de plano de fundo de download e publicar o resultado no thread da interface do usuário (forneça a imagem de volta). Veja Referência Android ligação
BenJaminSila
11
@BenJaminSila mudando o plano de fundo no AsyncTask? Mesmo?
USER25
11
@ user25 "assumindo que você está baixando esta imagem"
forresthopkinsa 9/17/17
"Quando esta mensagem aparece no emulador Android e o número de quadros ignorados é bastante pequeno (<100), você pode apostar com segurança se o emulador está lento" Isso ainda se aplica hoje? Os emuladores estão ficando bem rápidos, certo?
Robin Dijkhof
243

Como outros responderam acima, "Ignorados 55 quadros!" significa que algum processamento pesado está em seu aplicativo.

Para o meu caso, não há processo pesado no meu aplicativo. Eu dupliquei e tripliquei tudo e removi os processos que acho um pouco pesados.

Removai fragmentos, atividades e bibliotecas até restar apenas o esqueleto. Mas ainda assim o problema não desapareceu. Decidi verificar os recursos e encontrei alguns ícones e os antecedentes que utilizo são muito grandes, pois esqueci de verificar o tamanho desses recursos.

Portanto, minha sugestão é que, se nenhuma das respostas acima ajudar, você também pode verificar o tamanho dos arquivos de recursos.

Sithu
fonte
11
Trabalhou para mim também. Eu tinha um aplicativo que fazia muito pouco trabalho, mas era lento e lento. Eu continuava recebendo logs de quadros ignorados. Depois que removi o plano de fundo da minha atividade, tudo estava bem. Obrigado!
akrabi
Ótima resposta, acredito que esse foi exatamente o meu problema. Tentei várias outras soluções (bastante envolvidas) e o aplicativo ficou lento demais. Tirei todos os serviços da web e tentei otimizar meu código até o osso. Não funcionou, então eu vi isso. Assim que removi minha imagem de plano de fundo (maior imagem que tenho), o aplicativo funciona o mais rápido que você pode clicar nas coisas, mesmo com o antigo código "lento".
M Barbosa
você fez meu dia!
Nicolas Mastromarino
:) Você é um gênio absoluto.
precisa saber é o seguinte
@batsheva não é necessário ter 1 KB. Depende das suas necessidades, digamos que você precise de uma imagem mais nítida, você pode usar uma resolução mais alta, mas certifique-se de dividir em tamanhos diferentes nas diferentes pastas de recursos.
Sithu
61

Eu também tive o mesmo problema.
O meu foi um caso em que eu estava usando uma imagem de fundo que estava em drawables.That imagem em particular era de aproximadamente 130kB e foi usado durante a tela inicial e home page no meu aplicativo Android.

Solução - Acabei de mudar essa imagem específica para a pasta drawables-xxx de drawables e consegui liberar muita memória ocupada em segundo plano e os quadros que estavam pulando não estavam mais pulando.

Atualizar Use a pasta de recursos desenháveis ​​'nodp' para armazenar arquivos de desenhos em segundo plano.
Uma pasta drawable qualificada para densidade ou nodpi drawable terá precedência?

Prakhar1001
fonte
7
Mudei minha imagem de fundo grande de drawable para mimap-xxxhdpi e ele fez o truque!
Bgplaya 16/05
Você ajudou muito. Graças
N.Droid
2
Esta solução está fazendo o truque. Estou usando pasta drawable-xxxhdpiem vez drawableo que reduz drasticamente a memória usada (~ 70 por cento menos). Também é bom saber que telas com o mesmo tamanho variam em tamanho de DPI. A proporção em pixels entre eles é ldpi = 1:0.75, mdpi = 1:1, hdpi = 1:1.5, xhdpi = 1:2, xxhdpi = 1:3, xxxhdpi = 1:4. Ao usar a drawable-xxxhdpipasta, você permite reduzir a escala das imagens para o tamanho da tela do seu dispositivo, o que reduz o consumo de memória e CPU.
Timo Bähr
2
Mover imagens de drawablepara drawable-nodpiimpede que o aplicativo seja recebido Out of Memory Error.
Shruti
Oh meu Deus ... obrigado! Eu tinha uma imagem dentro da pasta drawable e isso tornava meu aplicativo lento como o inferno (embora a imagem tivesse apenas 100kb !!!). Depois de gerar os arquivos drawable-xxx (usei o Importador Drawable Android), meu aplicativo fica muito rápido. Muito obrigado!
error1337
20

Outra causa comum de atrasos no thread da interface do usuário é o acesso SharedPreferences. Quando você chama um PreferenceManager.getSharedPreferencese outros métodos semelhantes pela primeira vez, o arquivo .xml associado é imediatamente carregado e analisado no mesmo encadeamento .

Uma das boas maneiras de combater esse problema é acionar o primeiro carregamento de SharedPreference a partir do encadeamento em segundo plano, iniciado o mais cedo possível (por exemplo, da onCreateclasse Application). Dessa forma, o objeto de preferência já pode ser construído no momento em que você deseja usá-lo.

Infelizmente, às vezes é necessário ler um arquivo de preferência durante as fases iniciais da inicialização (por exemplo, na Atividade inicial ou até no próprio Aplicativo). Nesses casos, ainda é possível evitar o bloqueio da interface do usuário usando MessageQueue.IdleHandler. Faça tudo o que precisar para executar no encadeamento principal e instale o IdleHandler para executar o código assim que sua Atividade tiver sido totalmente desenhada. Nesse Runnable, você poderá acessar as SharedPreferences sem atrasar muitas operações de desenho e deixar o Choreographer infeliz.

user1643723
fonte
11
Nesse caso, você deve preferir o método apply () ao invés do commit (). O método apply () não pode bloquear a interface do usuário. Você pode procurar aqui developer.android.com/training/data-storage/shared-preferences
Emre Gürses
16

Tente usar as seguintes estratégias para melhorar o desempenho do seu aplicativo:

  • Use a programação multithreading, se possível. Os benefícios de desempenho são enormes, mesmo se o seu smartphone tiver um núcleo (os threads podem ser executados em diferentes núcleos, se o processador tiver dois ou mais). É útil separar a lógica do aplicativo da interface do usuário. Use threads Java, AsyncTask ou IntentService. Verifique isso .
  • Leia e siga as diversas dicas de desempenho do site de desenvolvimento do Android. Confira aqui .
MigDus
fonte
3
seu primeiro link exige que você "... tenha uma conta validada ..." para acessá-lo.
chornge
9

Eu tive o mesmo problema. O Emulador do Android funcionou perfeitamente no Android <6.0. Quando usei o emulador Nexus 5 (Android 6.0), o aplicativo funcionava muito lentamente I/Choreographer: Skipped framesnos logs.

Portanto, resolvi esse problema alterando a hardwareAcceleratedopção de arquivo Manifest para true:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application android:hardwareAccelerated="true">
        ...
    </application>
</manifest>
phen0menon
fonte
8

Não sou especialista, mas recebi essa mensagem de depuração quando queria enviar dados do meu aplicativo Android para um servidor da web. Embora eu tenha usado a classe AsyncTask e feito a transferência de dados em segundo plano, para recuperar os dados do resultado do servidor, usei o método get () da classe AsyncTask, que torna a interface do usuário síncrona, o que significa que sua interface do usuário estará aguardando muito tempo. Portanto, meu conselho é fazer com que seu aplicativo execute todas as tarefas orientadas à rede em um thread separado.

saba
fonte
6

Otimize suas imagens ... Não use imagens maiores que 100 KB ... O carregamento de imagens exige muita CPU e faz com que seu aplicativo seja interrompido.

HarshitG
fonte
4
Diminuir o tamanho da imagem, quer por código Java ou uso Photoshop para cortar imagens .. também imagens compressa utilizando compressor.io
HarshitG
5

Eu tive o mesmo problema. No meu caso, eu tinha 2 layouts relativos aninhados. O RelativeLayout sempre precisa fazer duas passagens de medida. Se você aninhar RelativeLayouts, você obtém um algoritmo de medição exponencial.

Radoslav
fonte
4

isso geralmente acontece quando você está executando processos enormes no thread principal. não há problema em ignorar quadros com menos de 200. mas se você tiver mais de 200 quadros ignorados, pode diminuir a velocidade do thread da interface do usuário do aplicativo. o que você pode fazer é executar esses processos em um novo thread chamado worker thread e, depois disso, quando você quiser acessar e executar sth com o thread da interface do usuário (por exemplo: faça algo com visualizações, findView etc ...), use o manipulador ou o runOnUiThread (Eu gosto mais disso) para exibir os resultados do processamento. isso absolutamente resolve o problema. O uso de threads de trabalho é muito útil ou deve ser usado quando se trata desses casos.

Hossein Karami
fonte
1

Eu tive o mesmo problema. Quando eu corri o código em outro computador, funcionou bem. No meu, no entanto, ele exibia "O aplicativo pode estar fazendo muito trabalho em seu encadeamento principal".

Resolvi meu problema reiniciando o Android studio [Arquivo -> Caches / Reiniciar invalidados -> clique em "Invalidar e reiniciar"].

sonida
fonte
Não sei por que sua solução funcionou. De qualquer forma obrigado.
Bhuvanesh BS 14/09
1

No meu caso, foi porque eu acidentalmente defini um ponto de interrupção em um método. Depois que a apaguei, a mensagem foi embora e o desempenho melhorou bastante.

FractalBob
fonte
0

Meu aplicativo teve o mesmo problema. Mas não estava fazendo outra coisa senão exibir uma lista de cartões e texto. Nada rodando em segundo plano. Mas depois de alguma investigação, descobriu que a imagem definida para o fundo do cartão estava causando isso, mesmo sendo pequena (350kb). Em seguida, converti a imagem em imagens de 9 patches usando http://romannurik.github.io/AndroidAssetStudio/index.html .
Isso funcionou para mim.

naamadheya
fonte
0

Depois de fazer muita pesquisa e desenvolvimento sobre esse assunto, obtive a solução,

No meu caso, estou usando o Serviço que será executado a cada 2 segundos e, com o runonUIThread, fiquei imaginando que o problema estava lá, mas não ocorreu. A próxima edição que eu encontrei é que estou usando uma imagem grande no App de maio e esse é o problema.

Eu removi as imagens e defina novas imagens.

Conclusão: - Examine o seu código: existe algum arquivo bruto que você esteja usando é de tamanho grande.

Hector Morris
fonte
0

Leia primeiro o aviso. Diz mais carga no segmento principal. Então, o que você precisa fazer é apenas executar funções com mais trabalho em um thread.

de_billa_
fonte
-1

Eu tive o mesmo problema ao desenvolver um aplicativo que usa muitos arquivos png desenháveis ​​no layout da grade. Eu também tentei otimizar meu código o máximo possível .. mas não funcionou para mim .. Então eu tentei reduzir o tamanho desses png .. e acho que está funcionando absolutamente bem .. Então, minha sugestão é reduzir tamanho dos recursos desenháveis, se houver.

Shubham Ranakoti
fonte