1) O documento discute Fragmentos no Android, incluindo o que são fragmentos, sua versão de introdução, classes de suporte, ciclo de vida e tipos de uso.
2) Fragmentos representam partes de uma activity e permitem um design modular que se adapta a diferentes orientações. Eles foram introduzidos no Android Honeycomb.
3) Há classes de suporte que permitem o uso de fragmentos em versões anteriores ao Honeycomb, e fragmentos podem ser adicionados staticamente no layout ou dinamicamente em tempo de execução.
3. Ementa
O que é um fragmento ?
Qual versão surgiu ?
Suporte em plataformas anteriores ao HoneyComb.
Classes de suporte;
Baixando o pacote de compatibilidade;
Ciclo de Vida de um Fragment;
Tipos de Uso(Dinâmico ou Estático);
Manipulando mudanças em Runtime;
Comunicação com à Atividade;
Inicialização Avançada;
Algumas SubClasses de Fragment;
4. O que é um fragmento ?
• É uma classe que implementa uma porção de uma activity.
• Representa uma operação em particular ou interface rodando dentro
de uma Activity maior.
• Permite um design de activities mais modular, fazendo com que uma
aplicação se adapte facilmente a diferentes orientações e resoluções.
• Fragments devem ser embutidos em activities, ou seja, eles não
podem rodar sem estarem associados a uma activity.
• É comum definir fragments que definam seus proprios layouts, e estes
vivem dentro da hierarquiva de view da propria activity.
• È possivel ter um fragment sem UI.
• Possui seu proprio ciclo de vida e muito proximo do ciclo de vida da
activity que a contém.
• Mais importate, você pode adicionar e remover fragments
dinamicamente.
5. Qual versão surgiu ?
Foram implementados no android Honeycomb, API 11. As principais
classes relacionadas são:
android.app.Fragment - Classe base para definição de fragments.
android.app.FragmentManager - Classe para iteragir com
fragments dentro de uma activity.
android.app.FragmentTransaction - Classe para suportar um
conjunto de operações atômicas com fragments, por exemplo :
adicionar, remover e substituir.
6. Suporte para versões antigas
O Google provê um pacote de compatibilidade que permite com
que aplicações que utilizem fragments rodem perfeitamente em
smartphones com android anterior ao HoneyComb.
Este pacote pode ser utilizado no android 1.6 (API 4) ou
anteriores.
Se você escrever sua aplicação utilizando o pacote de suporte,
você estara forçando com que o android sempre utilize essas
classes mesmo em plataformas mais novas(Jelly Bean, por
exemplo), ou seja, o android não irá forçar carregamento da
implementação nativa.
7. Classes de suporte
São essas as classes relacionadas ao pacote de suporte :
android.support.v4.app.FragmentActivity – Classe base para todas as
activities que desejem utilizar o pacote de suporte.
android.support.v4.app.Fragment – Classe base para definição de fragments
android.support.v4.app.FragmentManager - Classe para iteragir com
fragments dentro de activities.
android.support.v4.app.FragmentTransaction – Classe para realizar
operações atômicas nos fragments, tais como: inclusão, remoção e
substituição.
Obs: Para usar o pacote de compatibilidade na hora de criar a activity, você deve extender de
“android.support.v4.app.FragmentActivity” ao invés de android.app.Activity ou uma de suas
subclasses.
8. Baixando o pacote de compatibilidade
Basta baixar o componente
“Android Compatibility
Package” utilizando o
Android SDK.
9. Usando o pacote de compatibilidade
Para usar o pacote de
compatibilidade, você deve
adicionar ele para o buildpath
do seu projeto..
Ache a opção ao lado no ADT;
10. Ciclo de vida de um Fragment
Assim como uma Activity, um
fragment é um exemplo de
padrão de projeto : “Template
Method”;
O Ciclo de vida da atividade na
qual o fragmento vive afeta
diretamente o ciclo de vida do
fragment;
Cada callback do ciclo de vida da
activity resulta em um callback
para o ciclo de vida do fragment.
Por exemplo, quando a activity
recebe onPause(), cada fragmento
da activity reccebe onPause().
11. Ciclo de vida de um Fragment
Os Fragments possuem um ciclo de vida a par que trabalha em conjunto com o ciclo
de vida da activity que o contem.
• onAttach(Activity) – Chamado quando o fragmento tem sido adicionado a Activity.
• onCreateView(LayoutInflater, ViewGroup, Bundle) – Chamado para criar a View
associada ao Fragmento.
• onActivityCreated(Bundle) – Chamado quando o método onCreate() da activity
retornou.
• onDestroyView() - chamado quando a hieraquia de view associada ao fragmento
tem sido removida.
• onDetach() - Chamado quando o fragmento tem sido dessaciado da Activity.
Obs: Quando sobrescrevendo esses CallBack de ciclo de vida(Com excessão de onCreateView()) você deve
chamar através da implementação da superclasse do método. Caso contrário uma exception é lançada em
runtime.
12. Criando um Fragmento
Cada fragmento deve herdar da classe “Fragment”;
Muito dos métodos da classe Fragment são analogos aos
encontrados na classe Activity.
• onCreate(Bundle) – Inicializa recursos utilizados pelo fragment,
exteto os que são relacionados a interface do usuário.
• onCreateView(LayoutInflater, ViewGroup, Bundle) – Cria e
retorna uma hierarquia de View associada com o fragmento.
• onResume() - Aloca “expensive” recursos (Em termos de tempo
de bateria, custo monetario e etc.), Tal como um receiver para
“location updates”, “sensor updates” e etc.
• onPause()Release “expensive” resources. Commit any changes
that should be persisted beyond the current user session.
13. Adicionando o Fragmento na Activity
• Existem duas maneiras de adicionar um
fragmento a uma activity, são eles :
– Estaticamente, atraves do uso da tag
<fragment> diretamente no layout;
– Dinamicamente, Adicionando-o a algum
ViewGroup existente através de Transações.
14. Incluindo um Fragmento
Estaticamente
Modo mais simples de inclusão de um fragmento da Activity;
Isto funciona bem se o fragmento deveria estar presente no layout;
Entretanto, esta abordagem não permite que você remova dinamicamente o
fragmento em runtime;
No arquivo de layout da activity simplesmente utilize a tag <fragment>/
Use android:name para prover o nome totalmente qualificado da classe de
fragmento;
Cada fragmento requer um identificador único que o sistema pode usar para
restaurar o fragmento se a activity for reiniciada.
Existem três modos de prover um ID para o fragmento:
Através do atributo android:id com um id único;
Fornecendo o atributo android:tag com uma String única;
Se não prover nenhum dos atributos acima. O sistema usa o ID do fragment’s
container view.
15. Incluindo um Fragmento
dinamicamente
Em qualquer momento durante o funcionamento da activity, você pode incluir
um fragmento.
1.Primeiro, use Activity.getFragmentManager() para pegar uma referencia
a FragmentManager;
2.Invoque FragmentManager.beginTransaction() para pegar uma instancia
de FragmentTransaction;
3.Instancie uma instancia de fragment;
4.Use o método FragmentTransaction.add() para adicionar o fragmento
ao ViewGroup da activity, especificado por um ID. Opcionalmente, você também
pode fornecer uma String, “tag” para identificar o fragmento;
5.Commitar a transação usando FragmentTransaction.commit();
FragmentManager fragmentManager = getFragmentManager()
// Or: FragmentManager fragmentManager = getSupportFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
17. Exemplo
Exemplo simples que demonstra
A utilização de fragmentos para Fragmento A
criar uma com duas formas de
formulário. Activity
Fragmento B
Exemplo: Aula03_HelloFragments.zip
18. Manipulando mudanças de
configuração em Runtime
Quando o sistema destroi e recria a atividade por causa de uma
mudança de configuração, a atividade automaticamente reinstancia
fragmentos existentes.
• Isto não é um problema para “static” fragments declarados no layout
da activity.
• Mas para “dynamic” fragments, você precisará testar para saber se
isto está acontecendo e previnir a criação de uma segunda instancia
do fragmento.
Para testar se o sistema esta recriando à activity, basta checar se
o bundle passado como argumento para o método onCreate() é null.
• Se ele não é nulo entao o sistema está recriando a activity, neste caso,
a atividade automaticamente irá reinstanciar os fragmentos
existentes.
• Se é null você pode seguramente instanciar seu fragmento.
Exemplo a seguir !
19. Exemplo
Logo abaixo, um exemplo de manipulação de mudança de configuração em runtime, nesse caso,
evitando a reinstanciação do mesmo fragment.
public void onCreate(Bundle savedInstanceState) {
// ...
if (savedInstanceState == null) {
FragmentManager fragmentManager = getFragmentManager()
// Ou: FragmentManager fragmentManager = getSupportFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
}
20. Salvando o Estado de Um Fragmento
A classe Fragment suporta o método onSaveInstanceState do
mesmo modo que a classe Activity, mas em contra partida a classe
Fragment não suporta o método onRestoreInstanceState
• A implementação padrão salva o estado de todos os fragmentos
que possuem ID;
• Você pode sobrescrever este método para gravar alguma
informação adicional relacionada ao estado do fragmento.
• Se o sistema esta recriando o fragmento de um estado prévio, ele
provê uma referencia para o Bundle(Contento o estado) passado
para os métodos onCreate(), onCreateView() e on
ActivityCreated();
21. Mantendo fragmentos através da
recriação da Activity
• Quando uma activity é recriada os fragmentos também são
recriados.
• Chame o método
Fragment.setRetainInstance(boolean) com o valor
true para solicitar ao sistema que mantenha a instancia
atual caso a atividade seja recriada.
• Se invocado, quando a atividade é recriada, os métodos do
gragmento: onDestroy() e onCreate() não são invocados.
• Todos os outros métodos do ciclo de vida do fragmento são
invocados em sua sequencia típica.
Se você usar setRetainInstance(true), então o bundle que é passado como argumento para os
métodos onCreateView() e onActivityCreated() será sempre nulo, afinal o fragmento não será
recriado.
22. Mantendo fragmentos através da
recriação da Atividade
• “Retained fragments ” podem ser muito uteis para propragação de
informações de estado, especialmente “thread management”.
• Por exemplo, um fragmento pode servir como “host” para uma
instancia de Thread ou AsyncTask, gerenciando a operação.
• O método Activity.onRetainNonConfigurationInstance(), o qual
tradicionalmente tem sido criado para este proposito, está
depreciado a partir da API 11 em troca das capacidades do método
setRetainInstance() do fragment.
Se você está usando a biblioteca de compatibilidade, a classe FragmentActivity sobrescreve o
método onRetainNonConfigurationInstance() fazendo ele “final” para implementar as
capacidades de retenção.
23. Usando fragmentos sem Layouts
• Não é obrigatório que um fragmento possua UI.
• Por exemplo, se o fragmento foi criado apenas para coordenar uma
thread !
• Quando o fragmento não possui UI, não é necessário sobrescrever o
método onCreateView().
• Você deve adicionar o fragmento para à atividade usando
FragmentTransaction.add(Fragment, String), provendo uma tag String
única para identificar o fragmento.
Ex(Activity Code) :
FragmentManager fragmentManager = getFragmentManager()
// Or: FragmentManager fragmentManager = getSupportFragmentManager() FragmentTransaction
fragmentTransaction = fragmentManager.beginTransaction();
BackgroundFragment fragment = new BackgroundFragment(); fragmentTransaction.add(fragment,
"thread_manager");
fragmentTransaction.commit();
24. Procurando fragmentos
• A classe FragmentManager tem metodos para
encontrar fragmentos contidos dentro de uma
atividade, são eles:
– findFragmentById(int id) encontra o fragmento com o
ID especificado.
– findFragmentByTag(String tag) encontra o fragmento
com a tag especificada.
• Ambos destes métodos retornam uma referencia
para o fragmento ou null se nenhum fragmento é
encontrado.
25. Operações com Fragmentos
Você pode executar muitas outras operações com fragmentos dinamicos, tais
como: adicionar, remover e mudar a visibilidade.
Cada conjunto de mudanças que você comita é chamada de transação.
Para realizar operações com Fragmentos você utiliza a
classe FragmentTransaction, esta possui os seguintes métodos :
– add() : Adiciona um fragmento a atividade.
– remove(): Remove o fragmento da atividade. Esta operação destroy a instancia do
fragmento ao menos que a transação seja adicionada ao “transaction back stack”.
– replace(): Remove o fragmento da UI e substitui ele por outro.
– hide(): Esconde o fragmento da UI (Sem destrui a hierarquia de Views).
– show(): Mostra um fragmento previamente escondido.
– detach() (API 13) Desanexa o fragmento da UI, destruindo a hieraquia de View, mas
mantendo a instancia do fragmento.
– attach() (API 13) Reanexa o fragmento que tenha sido previamente
desanexado, recriando a hierarquia de view.
Você não pode remover, substituir, desanexar ou anexar um fragmento
declarado no layout da activity(Static Fragments).
26. Executando transações de Fragmento
Para executar uma transação com fragmentos, você deve :
Obter uma instancia de FragmentTransaction chamando
FragmentManager.beginTransaction().
Executar qualquer numero de operações usando a instancia da transação.
A maioria das operações com FragmentTransaction retorna uma
referencia para a mesma FragmentTransaction , permitindo
encadeamento de método.
Chamar commit() para aplicar a transação na atividade.
Você pode comitar uma transação utilizando commit() somente antes da activity
salvar seu estado (antes do sistema invocar Activity.onSaveInstanceState()). Se você
tentar executar depois desse ponto, uma exceção será lançada.
27. Gerenciando o “Fragment Back Stack”
• Similar ao conceito de “Back Stack” para Atividades, você tem a opção de salvar as
operações de fragmentos em uma “Back Stack” gerido pela Atividade;
• Se você adicionar as operações de transação para a “Back Stack”, então o usuário
pode navegar para trás atraves das mudanças realizadas pelas transações apenas
presionando o “Back Button”;
• Se todos os fragmentos tiverem sido removidos da “Back Stack” ao pressionar o
“Back Button”, isso irá destruir a atividade.
• Para adicionar uma transação para a “Back Stack”, basta
chamar FragmentTransaction.addToBackStack(String) antes de comitar a transação.
• O argumento string é opcional e serve para identificar o estado da “Back Stack”. A
classe FragmentManager tem um método chamado popBackStack(), qual pode
retornar para um previo estado da “Back Stack” com um dado nome.
• Se você adicionar multiplas mudanças para a transação e
chamar addToBackStack(), então todas as mudanças aplicadas antes de você chamar
commit() são adicionadas a back stack como uma única transação e o “BackButton”
irá reverte-las todas juntas.
• Se você chamar addToBackStack() quando removendo e substituindo um fragmento:
– O sistema invoca onPause(), onStop(), e onDestroyView() no fragmento quando ele é colocado no
“back stack”.
– Se o usuário navegar de volta, o sistema invoca
onCreateView(), onActivityCreated(),onStart(), e onResume() no fragmento.
28. Comunicando um Fragmento e uma
Atividade
Na comunicação entre Atividade e Fragmento,
podemos:
– Chamar métodos publicos do fragmento de dentro de uma
atividade;
– Encontrar fragmentos associados à Atividade usando
FragmentManager com os
métodos: findFragmentById() ou findFragmentByTag().
– Obter a referencia para à Atividade
chamando Fragment.getActivity;
29. Inicialização Avançada de Fragmentos
• È possivel utilizar o método Na activity :
setArguments(Bundle) passa
ndo um bundle com os
argumentos. No fragment :
• Dentro do fragmento basta
invocar o método
getArguments().
30. Criando Dialogos usando Fragmento
• A partir do Honeycomb (API 11), the Activity class’s “managed
dialog” methods are deprecated in favor of fragments.
• A classe DialogFragment serve como base para um dialogo baseado
em fragments;
• Esta classe contem um objeto dialogo que é exibido de acordo com
seu estado;
• Você deveria controlar o dialogo usando os métodos fornecidos
pela classe fragment;
• Se você planeja usar o fragmento somente como um dialogo,
sobrescreva o método onCreateDialog() e retorne uma instancia
de Dialog ou uma de suas subclasses.
• Se você quer usar o fragment as ou como um dialogo ou como um
fragmento normal, sobrescreva o método onCreateView() e retorna
a hierarquia de view.
31. Exemplo
No Exemplo abaixo podemos observar as práticas:
Uso de interface para comunicação com Activity;
Uso do método show() de Fragment Manager;
Uso das classes de suporte para exibição do Dialogo;
Exemplo: Aula03_SimpleDialogFragment.zip
32. MasterDetail com ADT
Um exemplo bem interessante e que
é um forte candidato a estudo da
tecnologia de fragments é o exemplo
Fornecido pelo próprio ADT.
• Aula03_MasterDetailFragment.zip
33. Algumas subclasses de Fragment
Existem algumas subclasses de e Fragment
projetadas para usos comuns em aplicações
Android:
• ListFragment – Um fragmento que
automaticamente gerencia um ListView.
Analogo a classe ListActivity.
• WebFragment – Um fragmento que cria e
gerencia um WebView.
34. Referencias
Professional Android 4 Application Development, Wei-Meng Lee, Wiley 2011.
Android Training : http://developer.android.com/training/index.html.