sábado, 8 de setembro de 2012

Ciclo de Vida de uma Activity

Olá pessoal,

Hoje vamos abordar mais um assunto importante no desenvolvimento de aplicações Android, o ciclo de vida de uma activity.

Inclusive, vou abrir com uma frase interessante do livro Professional Android 4 Application Development, que diz o seguinte:


"A good understanding of the Activity lifecycle is vital to ensure that your application provides a
seamless user experience and properly manages its resources."

Em português

"Um bom entendimento do ciclo de vida da Activity é vital para garantir que sua aplicação provê uma experiencia continua de usuário e gerencia seus recursos apropriadamente."

Isso significa que devemos estar conscientes do que acontece quando a nossa Activity é iniciada, está em processo e é finalizada, e se neste processo está utilizando e liberando os recursos corretamente. Se tomarmos como exemplo um aplicativo que utiliza a camera do dispositivo, temos que "prender" o recurso somente quando necessário e liberá-lo quando não estamos utilizando. Mas o que quer dizer "somente quando necessário"? Ainda falando de um aplicativo que utiliza a camera do dispositivo, imagine que você está utilizando o aplicativo e de repente você precisa abrir o seu gerenciador de e-mails, que é uma outra aplicação, enquanto você estava vendo o seu aplicativo, sua Activity estava ativa, no momento em que você abriu seu gerenciador de e-mail sua aplicação ficou escondida e teoricamente você não está utilizando a camera, neste momento você deve liberar este recurso. 

Pilha de Activities


No Android há uma pilha de Activities, onde sempre a ultima  Activity aberta fica visível, exceto quando é uma  Activity em background. Enquanto ela está visível, ela tem prioridade de processamento, pois em tese, é a  Activity que o usuário está utilizando. 
De tempos em tempos o sistema operacional verifica se há  Activities que não estão sendo mais utilizadas na fila, estas  Activities são finalizadas sem que o usuário seja notificado, assim o sistema operacional consegue liberar recursos. Se você por exemplo abrir um jogo como o Angry Birds por exemplo, se você o deixar em segundo plano, um tempo depois quando você for abrir o jogo carrega tudo novamente, pois o Android detectou que esta era uma  Activity que não estava sendo utilizada.

Estados da Activity


As Activities podem estar em quatro estados:

Active: Quando está visível e com foco. O sistema operacional neste momento faz o possível para mantê-la ativa. Quando não está mais em foco, ela entra em pausa.

Paused: Quando a  Activity está visível mas não está sendo utilizada pelo usuário por não estar com foco.

Stopped: Quando a  Activity não está visível para o usuário ela para e fica na memória se tornando forte candidata a se removida da memória para liberar recursos.

Inactive: Ocorre quando a Activity está morta e antes de ser chamada novamente. Esta Activity é removida da memória para liberar recursos.

É importante saber que esta transição de estados entre as Activities deve ser transparente para o usuário e se o aplicativo necessitar manter o estado do aplicativo entre abrir e fechar, o estado deve ser salvo e recuperado entre estes estados. 
A imagem abaixo foi extraída do livro Professional Android 4 Application Development e representa de uma maneira simples e fácil de entender o ciclo de vida de uma Activity.


Eu escrevi um aplicativo simples para rastrear todos os eventos que a Activity sofre durante seu ciclo de vida. No exemplo abaixo é possível visualizar a chamada de todos os eventos, e também as funções auxiliares que criei.

package com.example.ciclo.vida.activity;

import android.os.Bundle;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

private History history = History.getInstance();

@Override
protected void onStart() {
super.onStart();
this.history.setHistoryText("onStart");

}

@Override
protected void onRestart() {
super.onRestart();
this.ShowHistory("onRestart");

}

@Override
protected void onResume() {
super.onResume();
this.ShowHistory("onResume");

}

@Override
protected void onPause() {
super.onPause();
this.ShowHistory("onPause");
}

@Override
protected void onStop() {
super.onStop();
this.ShowHistory("onStop");
}

@Override
protected void onDestroy() {
super.onDestroy();
this.ShowHistory("onDestroy");
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.ShowHistory("onCreate");

if (savedInstanceState != null) {
this.ShowHistory(savedInstanceState
.getString(getString(R.string.state_history)));
}

}

@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
outState.putString(getString(R.string.state_history),
history.getHistoryText());
this.ShowHistory("onSaveInstanceState");
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onRestoreInstanceState(savedInstanceState);

this.history.clearHistoryText();
this.ShowHistory("onRestoreInstanceState");
this.ShowHistory(savedInstanceState
.getString(getString(R.string.state_history)));

}

private void ShowHistory(String newState) {

if (newState != "") {
this.history.setHistoryText(newState);

TextView textView = (TextView) findViewById(R.id.mainActivity_textView);
textView.setText(history.getHistoryText());
}
}

}

Atente ao fato de que todas as chamadas aos eventos são sobrecargas definidas pelo atributo override. Quando você executar seu aplicativo irá ver uma imagem semelhante a abaixo:

Faça mais alguns testes, como rotacionar o aparelho, ou apertar o botão voltar ou o home, você verá que os status serão incrementados. Este exemplo mostra também como gravar o estado da Activity e recarregar depois através do onSaveInstanceState e do onRestoreInstanceState. 

O código fonte deste aplicativo pode ser baixado aqui.

Abraço a todos.











Nenhum comentário:

Postar um comentário