Ótimos aplicativos não perdem o progresso do usuário e o estado do app. Eles salvam automaticamente os dados necessários sem interromper o usuário e restauram os dados se e quando necessário de uma forma transparente – por exemplo, após voltar de um estado em background ou um desligamento inesperado.
Infelizmente, muitas aplicações web fazem isso errado, porque elas não levam em conta o ciclo de vida móvel: elas estão ouvindo os eventos errados que podem nunca ser disparados, ou ignoram totalmente o problema, causando o alto custo da má experiência do usuário. Para ser justo, a plataforma web também não faz isso ser fácil, expondo muitos eventos diferentes: visibilityState, pageshow, pagehide, beforeunload, unload. Qual devemos usar, e quando?
Você não pode confiar nos eventos pagehide, beforeunload e upload para serem disparados em plataformas móveis. Isso não é um bug no seu navegador favorito; isso acontece devido à forma como todos os sistemas operacionais móveis funcionam. Um aplicativo ativo pode fazer a transição para um “estado de background” por meio de várias rotas:
- O usuário pode clicar em uma notificação e mudar para um aplicativo diferente.
- O usuário pode invocar o gerenciador de tarefas e passar para um aplicativo diferente.
- O usuário pode apertar o botão “home” e ir para a tela inicial.
- O sistema operacional pode alternar o aplicativo em nome do usuário – por exemplo, devido a uma chamada telefônica recebida.
Depois que o aplicativo fez a transição para o estado de background, ele pode ser jogado fora sem qualquer cerimônia – por exemplo, o sistema operacional pode terminar o processo para recuperar os recursos, o usuário pode deslizar o aplicativo no gerenciador de tarefas para fechá-lo. Como resultado, você deve assumir que “fechamentos perfeitos” que disparam os eventos pagehide, beforeunload e unload são a exceção, não a regra.
Para proporcionar uma experiência de usuário confiável e consistente, tanto no desktop quanto no mobile, o aplicativo deve usar a API Page Visibility e executar sua sessão salva e restaurar a lógica sempre que o estado de visibilityChange mudar. Esse é o único evento com o qual a sua aplicação pode contar.
// query current page visibility state: prerender, visible, hidden var pageVisibility = document.visibilityState; // subscribe to visibility change events document.addEventListener('visibilitychange', function() { // fires when user switches tabs, apps, goes to homescreen, etc. if (document.visibilityState == 'hidden') { ... } // fires when app transitions from prerender, user returns to the app / tab. if (document.visibilityState == 'visible') { ... } });
Se você está contando com unload para salvar dados do estado, registrar e reportar para o Google Analytics, e executar outra lógica relevante, então você está perdendo uma grande parte das sessões provenientes do mobile, nas quais unload não irá disparar. Da mesma forma, se você está contando com evento beforeunload para avisar o usuário sobre os dados não salvos, então você está ignorando que “fechamentos perfeitos” são uma exceção, não a regra.
Use a API Page Visibility e esqueça que os outros eventos sequer existem. Trate cada transição visible como uma nova sessão: restaure o estado anterior, redefina seus contadores de análise, e assim por diante. Então, quando o aplicativo transitar para hidden, finalize a sessão: salve o usuário e o estado do aplicativo, balize suas análises, e execute todas as outras tarefas necessárias.
Se for necessário, com um pouco de trabalho extra, você pode agregar essas sessões baseadas em visibilidade dentro de fluxos maiores de usuários que respondem por aplicativo e troca de abas – por exemplo, reporte cada sessão para o servidor e agregue várias sessões juntas.
Considerações sobre a implementação prática
Em longo prazo, tudo que você precisa é da API Page Visibility. A partir de hoje, você vai ter que aumentá-la com um outro evento – pagehide, para ser específico – para o caso de “quando a página está sendo descarregada”. Para os curiosos, aqui está uma matriz completa de quais eventos disparam em cada navegador hoje (com base no meu teste manual):
- visibilityChange funciona de forma confiável para a mudança de tarefas em plataformas móveis.
- beforeunload é de valor limitado, uma vez que só é acionado em navegações de desktop.
- unload não dispara no mobile e no Safari para desktop.
A boa notícia é que Page Visibility abrange de forma confiável cenários de alternância de tarefas em todas as plataformas e fornecedores de navegadores. A má notícia é que hoje o Firefox é o único que dispara o evento visibilityChange quando a página é descarregada – Chrome, WebKit e Edge têm bugs com relação a isso. Uma vez que eles sejam resolvidos, visibilityState é o único evento que você precisa para fornecer uma grande experiência do usuário.
***
Ilya Grigorik faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://www.igvita.com/2015/11/20/dont-lose-user-and-app-state-use-page-visibility/