NullPointerException em onResume ao modificar botões, por quê?
-
14-11-2019 - |
Pergunta
Estou recebendo um NullPointerException gerado por vários de meus usuários e não consigo identificar qual é o problema. Ele é lançado nesta linha:
((Button)findViewById(R.id.speakEnglishButton)).setText("");
Não consigo ver o que está errado, o botão existe com esse ID, compila bem, funciona bem no meu emulador e em 2 dispositivos, no entanto, estou recebendo cerca de 100 erros sendo postados no meu console do desenvolvedor para usuários neste versão.
Olhando mais de perto o onResume :
@Override
protected void onResume()
{
super.onResume();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
boolean isButtonLabelsEnabled = sp.getBoolean("isButtonLabelsEnabled", false);
if (!isButtonLabelsEnabled)
{
((Button)findViewById(R.id.speakEnglishButton)).setText("");
((Button)findViewById(R.id.speakFrenchButton)).setText("");
((Button)findViewById(R.id.speakSpanishButton)).setText("");
((Button)findViewById(R.id.speakGermanButton)).setText("");
((Button)findViewById(R.id.speakItalianButton)).setText("");
}
else
{
((Button)findViewById(R.id.speakEnglishButton)).setText(getString(R.string.btnLblEnglish));
((Button)findViewById(R.id.speakFrenchButton)).setText(getString(R.string.btnLblFrench));
((Button)findViewById(R.id.speakSpanishButton)).setText(getString(R.string.btnLblSpanish));
((Button)findViewById(R.id.speakGermanButton)).setText(getString(R.string.btnLblGerman));
((Button)findViewById(R.id.speakItalianButton)).setText(getString(R.string.btnLblItalian));
}
}
Essencialmente, tudo o que estou fazendo é verificar se há um booleano de preferência salvo e, dependendo de seu valor, estou definindo rótulos nos botões ou definindo-os como espaços em branco.
Alguém pode aconselhar?
Obrigado
Solução
Faça tudo isso ((Button)findViewById(R.id.speakEnglishButton)).setText("");....em onCreate()
Adicionar
private Button mSpeakEngButton;
.....
Como variáveis de classe, inicialize-as em onCreate()
public void onCreate() {
....
mSpeakEngButton = ((Button)findViewById(R.id.speakEnglishButton));
}
Posteriormente no código, você pode modificar seus valores como mSpeakEngButton.setWhatever()
Outras dicas
Acho que a questão é que quando o usuário retoma a atividade o layout não está definido e, portanto, um findViewById()
não tem 'âncora' para procurar e, portanto, retorna nulo.
Você pode simplesmente mover a chamada para setContentView()
de onCreate
para onResume
(dado que você não está fazendo referência a visualizações em onCreate
.Para uso normal isso não faz diferença como no ciclo de vida do Android, onResume
é chamado diretamente depois onCreate
e antes que o usuário possa interagir com a atividade.
Na verdade, há um bug em alguns aplicativos onde você visita uma atividade, depois inicia outra, talvez sai do aplicativo para outra, retorna e depois retorna (através do botão Voltar) para a primeira atividade.Aqui, de repente, você vê uma tela preta.Isso porque o sistema “trocou” a primeira atividade e ao retornar apenas onResume
é chamado, mas não onCreate
, portanto não há chance de carregar o layout novamente lá.
Provavelmente isso é causado quando
((Button)findViewById(R.id.speakEnglishButton));
retorna nulo.Isso acontece se tal recurso não puder ser encontrado.Espontaneamente uma razão me vem à mente:Você não possui recursos padrão em seu layout.Que significa:Você deve ter pelo menos um layout "padrão", que se aplica a cada idioma/orientação/...que deve ser colocado na pasta “layout”.Simplesmente "layout".
Se você mantiver setContentView() em onResume() em vez de onCreate(), ocorrerá uma exceção de inflação, eu tentei isso.