Como criar um projeto impecável

Mesmo que seu aplicativo seja rápido e responsivo, algumas decisões de design ainda podem causar problemas aos usuários devido a interações não planejadas com outros aplicativos ou caixas de diálogo, perda inadvertida de dados, bloqueio não intencional, etc. Para evitar esses problemas, é útil entender o contexto em que seus aplicativos são executados e as interações do sistema que podem afetá-los. Tente desenvolver um aplicativo que interaja perfeitamente com o sistema e com outros aplicativos.

Um problema comum de integração ocorre quando o processo em segundo plano de um aplicativo, por exemplo, um serviço ou receptor de transmissão, abre uma caixa de diálogo em resposta a algum evento. Isso pode parecer um comportamento inofensivo, especialmente quando você está criando e testando seu aplicativo isoladamente no emulador. No entanto, quando seu aplicativo é executado em um dispositivo real, ele pode não ter o foco do usuário no momento em que o processo em segundo plano exibe a caixa de diálogo. Portanto, o app pode exibir a caixa de diálogo atrás do aplicativo ativo ou tirar o foco de outro app e exibir a caixa de diálogo na frente do que o usuário estava fazendo, como, por exemplo, uma chamada telefônica. Esse comportamento não seria adequado para seu aplicativo nem para o usuário.

Para evitar esses problemas, é importante que seu aplicativo use o recurso de sistema apropriado para notificar o usuário: as classes Notification. Com as notificações, seu aplicativo pode sinalizar ao usuário que um evento ocorreu, exibindo um ícone na barra de status em vez de focar e interromper o usuário.

Outro exemplo de problema de integração é quando uma atividade perde dados de estado ou do usuário inadvertidamente porque não implementa corretamente o onPause() e outros métodos de ciclo de vida. Ou então, se seu aplicativo expõe dados destinados ao uso por outros aplicativos, exponha-os por meio de um ContentProvider, em vez de fazer isso por um banco de dados ou arquivo bruto legível.

O que esses exemplos têm em comum é que envolvem uma boa cooperação com o sistema e outros aplicativos. O sistema Android foi projetado para tratar aplicativos como um tipo de federação de componentes fracamente acoplados, em vez de blocos de código de caixa preta. Isso permite que você, como desenvolvedor, visualize todo o sistema como apenas uma federação ainda maior desses componentes. Isso beneficia você, permitindo sua integração de forma limpa e integrada a outros aplicativos. Por isso, crie seu próprio código de forma a retribuir o favor.

Este documento discute problemas comuns de continuidade e como evitá-los.

Não descarte dados

Tenha sempre em mente que o Android é uma plataforma para dispositivos móveis. Pode parecer óbvio, mas é importante lembrar que outra atividade (como o aplicativo "Chamada telefônica recebida") pode aparecer sobre sua própria atividade a qualquer momento. Isso acionará os métodos onSaveInstanceState() e onPause() e provavelmente resultará no encerramento do seu aplicativo.

Se o usuário estava editando dados no seu aplicativo quando a outra atividade apareceu, seu aplicativo provavelmente perderá esses dados quando for encerrado. A menos, é claro, que você salve o trabalho em andamento primeiro. O "jeito Android" é fazer exatamente isso: os aplicativos para Android que aceitam ou editam a entrada precisam modificar o método onSaveInstanceState() e salvar seu estado de alguma forma adequada. Quando o usuário volta ao aplicativo, ele tem que conseguir recuperar os dados.

Um exemplo clássico do bom uso desse comportamento é um aplicativo de e-mail. Se o usuário estava escrevendo um e-mail quando outra atividade começou, o aplicativo precisa salvar o e-mail em andamento como rascunho.

Não exponha dados brutos

Se você não andaria pela rua sem roupa, seus dados também não deveriam. Embora seja possível expor certos tipos de aplicativo ao mundo, geralmente não é a melhor ideia. A exposição de dados brutos requer que outros aplicativos entendam o formato dos dados. Se você alterar esse formato, todos os outros aplicativos que não forem atualizados também serão corrompidos.

O "jeito Android" é criar um ContentProvider para expor seus dados a outros aplicativos por meio de uma API limpa, bem elaborada e de fácil manutenção. Usar um ContentProvider é muito parecido com a inserção de uma interface em linguagem Java para dividir e componentizar dois códigos fortemente acoplados. Isso significa que você poderá modificar o formato interno dos seus dados sem alterar a interface exposta pelo ContentProvider e sem afetar outros aplicativos.

Não interrompa o usuário

Se o usuário estiver executando um aplicativo (como o aplicativo "Telefone" durante uma chamada), é bem provável que ele tenha feito isso de propósito. Por isso, evite gerar atividades, exceto em resposta direta à entrada do usuário da Atividade atual.

Ou seja, não chame startActivity() a partir de BroadcastReceivers ou serviços que estejam em execução em segundo plano. Isso interromperá qualquer aplicativo que esteja sendo executado e deixará o usuário irritado. E pode piorar. Sua atividade pode se tornar um "ladrão de teclas" e receber uma das informações que o usuário estava fornecendo para a atividade anterior. Dependendo do que seu aplicativo faz, isso pode ser muito ruim.

Em vez de gerar UIs de atividade diretamente a partir do segundo plano, use o NotificationManager para definir notificações. Elas aparecerão na barra de status e o usuário poderá clicar nelas quando quiser para ver o que seu aplicativo precisa mostrar a ele.

Observe que isso não se aplica aos casos em que sua própria atividade já está em primeiro plano: nesse caso, o usuário espera ver sua próxima atividade em resposta à entrada.

Tem muito a fazer? Faça em uma linha de execução

Se seu aplicativo precisar executar algum cálculo caro ou de longa duração, provavelmente é uma boa ideia movê-lo para uma linha de execução. Isso evita que a temida caixa de diálogo "O app não está respondendo" seja exibida para o usuário, com o resultado final sendo o encerramento brutal do seu aplicativo.

Por padrão, todo o código em uma atividade, assim como todas as visualizações, é executado na mesma linha de execução. Essa é a mesma linha de execução que gerencia eventos da IU. Por exemplo, quando o usuário pressiona uma tecla, um evento de pressionamento de tecla é adicionado à fila da linha de execução principal da atividade. O sistema do manipulador de eventos precisa desvincular e manipular esse evento rapidamente. Se isso não acontecer, o sistema concluirá, após alguns segundos, que o aplicativo está inativo e perguntará ao usuário se pode encerrar.

Se você tiver um código de longa duração, executá-lo in-line na sua atividade executará o código na linha de execução do manipulador de eventos, bloqueando efetivamente o manipulador de eventos. Isso atrasará o processamento de entrada e resultará nas caixas de diálogo de ANR. Para evitar isso, coloque seus cálculos em uma linha de execução. Este documento discute como fazer isso: Criar um projeto responsivo.

Não sobrecarregue uma única tela de atividade

Qualquer aplicativo usável provavelmente terá várias telas diferentes. Ao projetar as telas da sua IU, use várias instâncias do objeto de atividade.

Dependendo do seu histórico de desenvolvimento, você pode interpretar uma atividade de forma parecida a um miniaplicativo Java, já que ela é o ponto de entrada para seu aplicativo. No entanto, isso não é muito preciso: ao passo em que uma subclasse de miniaplicativo é o ponto de entrada único para um miniaplicativo Java, uma atividade precisa ser considerada como um dos vários pontos de entrada possíveis para seu aplicativo. A única diferença entre sua atividade "principal" e qualquer outra que você possa ter é que a "principal" é a única que demonstrou interesse na ação "android.intent.action.MAIN" no seu XML file AndroidManifest.

Portanto, ao projetar seu aplicativo, pense nele como uma federação de objetos de atividade. Isso tornará seu código muito mais sustentável a longo prazo e também funcionará bem com o histórico de aplicativos e o modelo de pilha de retorno do Android.

Estenda temas do sistema

Quando se trata da aparência da interface do usuário, é importante não chamar atenção. Os usuários estranham aplicativos muito diferentes da interface que estão acostumados. Ao projetar suas IUs, evite usar suas próprias interfaces o máximo possível. Em vez disso, use um tema. É possível modificar ou estender as partes do tema que você precisa, mas, pelo menos, você está começando pela mesma base de UI de todos os outros aplicativos. Para ver todos os detalhes, leia Estilos e temas.

Projete sua interface para funcionar com várias resoluções de tela

Diferentes dispositivos com tecnologia Android serão compatíveis com resoluções de tela diferentes. Alguns poderão até mesmo mudar as resoluções instantaneamente, como, por exemplo, ao alternar para o modo paisagem. É importante garantir que seus layouts e drawables sejam flexíveis o suficiente para serem exibidos corretamente em várias telas de dispositivos.

Felizmente, é muito fácil fazer isso. Resumidamente, o que você precisa fazer é fornecer versões diferentes da sua imagem (caso use alguma) para as principais resoluções e, em seguida, projetar seu layout para acomodar várias dimensões. Por exemplo, evite usar posições codificadas e use layouts relativos. Se você fizer isso, o sistema lidará com o restante, e seu aplicativo terá uma boa aparência em qualquer dispositivo.

Prepare-se para uma rede lenta

Os dispositivos Android têm várias opções de conexão de rede. Todos terão uma provisão de acesso a dados, mas alguns são mais rápidos que outros. Entretanto, o menor denominador comum é o GPRS, o serviço de dados não 3G para redes GSM. Até dispositivos com 3G passarão muito tempo em redes não 3G, portanto, as redes lentas continuarão sendo uma realidade por muito tempo.

Por isso, sempre codifique seus aplicativos para minimizar os acessos à rede e à largura de banda. Não conte com a rapidez da rede, sempre se prepare para lentidão. Se os usuários estiverem em redes mais rápidas, ótimo. A experiência deles será melhor. O ideal é evitar o contrário. Aplicativos que funcionam bem por algum tempo, mas que, depois, ficam lentos com base na localização do usuário tendem a perder popularidade.

Uma possível pegadinha aqui é que é muito fácil cair nessa armadilha se você estiver usando o emulador, já que ele usa a conexão de rede do seu computador desktop. É quase garantido que ela será muito mais rápida que uma rede celular. Por isso, convém mudar as configurações no emulador para que simulem velocidades de rede mais lentas. Você pode fazer isso no Android Studio pelo AVD Manager ou com uma opção da linha de comando ao iniciar o emulador.

Não conte com touchscreen ou teclado

O Android é compatível com vários formatos de dispositivos. Essa é uma maneira sofisticada de dizer que alguns dispositivos Android terão teclados QWERTY completos, enquanto outros terão 40 teclas, 12 teclas ou até mesmo outras configurações de teclas. Da mesma forma, alguns dispositivos terão touchscreens, mas muitos não.

Ao criar seus aplicativos, lembre-se disso. Não faça suposições sobre layouts de teclado específicos, a menos que você esteja realmente interessado em restringir seu aplicativo para uso exclusivo nesses dispositivos.

Preserve a bateria do dispositivo

Um dispositivo móvel não é muito móvel se estiver constantemente conectado à tomada. Dispositivos móveis são alimentados por bateria, e quanto mais ela dura com uma carga, mais feliz todos ficam, especialmente o usuário. Dois dos maiores consumidores de energia da bateria são o processador e o rádio. É por isso que é importante criar seus aplicativos para o mínimo de trabalho possível e usar a rede com a menor frequência possível.

Para minimizar a quantidade de tempo que seu aplicativo usa o processador, basta escrever códigos eficientes. Para minimizar o consumo de energia do uso do rádio, gerencie as condições de erro corretamente e busque apenas o que você precisa. Por exemplo, não repita constantemente uma operação de rede se houver falha. Se ela falhou uma vez, é provável que o usuário não tenha sinal. Por isso, ela provavelmente falhará se você tentar imediatamente. Você só vai desperdiçar bateria.

Os usuários são muito inteligentes: se o programa usar muita bateria, eles vão perceber. A única coisa de que você pode ter certeza, nesse caso, é que seu programa não ficará instalado por muito tempo.