Quando começamos a estudar sobre o uso da API de Fragment do Android, é comum chegarmos a conclusão de que temos duas maneiras de adicionar Fragments no xml de layout.
Uma maneira é usar a tag fragment
atributindo ao atributo class
o fully qualified name do Fragment
que queremos usar.
Outra forma é usar uma tag de layout para delimitar o espaço e, programaticamente colocarmos o Fragment neste espaço através do FragmentManager
, FragmentTransaction
e id atribuído a tag de layout. As leituras no Android Developer nos induzem a tag de layout FrameLayout
, mas pode ser qualquer outra.
No entanto, uma questão que normalmente fica sem resposta é Em quais situações devo usar tag fragment ou tag de layout?
Tag Fragment
A tag fragment é mais adequada em casos que não será necessário substituir o fragment em tempo de execução. Isso pois, se for feito usando os métodos add
ou replace
do FragmentTransaction
, será notado um comportamento estranho pois ambos os métodos irão sobrepor o conteúdo do fragment atual, e ok, esperamos isso do add
mas não esperamos isso do replace
.
Aplicativos para tablets são um bom exemplo de utilização. Normalmente o xml de layout de um tablet tem um menu a esquerda e o conteúdo se abre a diretira. O menu é um forte candidato para se usar a tag fragment no seu xml de layout, pois o que se espera neste contexto é que ele sempre esteja lá.
O xml de layout neste caso seria assim:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="@+id/main"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<\/LinearLayout>
A renderização do layout acima seria algo mais ou menos assim:
A vantagem neste contexto é uma performance um pouco melhor na renderização da Activity. Desta forma, tão logo o layout seja carregado, operação que é iniciada após a chamada do método setContentView, o próprio Android se encarregará de instanciar o Fragment e carregá-lo, não necessitando ser feito programaticamente.
Considerando inclusive que se feito programaticamente, deve ser feito após o carregamento do layout, para que se possa recuperar os id’s e atribuir o novo conteúdo.
Tag de Layout
A tag de layout é mais adequada quando se pretende alterar o conteúdo ocupado por um fragment em tempo de execução.
Usando o mesmo exemplo anterior, em um smartphone, o xml de layout teria apenas um espaço que inicialmente carregaria o menu na tela inteira. Ao clicar em algum item, no mesmo lugar que se encontra o menu, deve ser carregado o conteúdo do item clicado. Ou seja, teremos que substituir o conteúdo atual por um novo conteúdo.
Para que isso seja possível, precisamos usar o método replace
da classe FragmentTransaction
. Este método irá substituir em tempo de execução o conteúdo atual da tag de layout por um novo Fragment.
Logo, nosso xml de layout ficaria assim:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="@+id/main"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
A renderização esperada do layout acima é algo mais ou menos assim (abaixo é possível perceber também o comportamento):
A desvantagem desta forma é que, mesmo o primeiro carregamento do Fragment, precisará ser feito programaticamente.
Segue o trecho de código para carregar um Fragment em uma tag de layout, normalmente colocamos este trecho no método onCreate da Activity:
/** Cria uma instância do Fragment a ser carregado */
MenuFragment menuFrag = new MenuFragment();
/** Pega a transação para trabalhar com Fragments */
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
/** Coloca o Fragment de menu no espaço delimitado pela tag de layout */
transaction.add(R.id.menu, menuFrag);
/** Confirma a transação. Neste momento ele sabe o que deve ser renderizado no espaço da tag de layout */
transaction.commit();
Apesar disso, ganhamos a flexibilidade de poder alterar a qualquer momento o conteúdo atual por outro Fragment, bastando utilizar o código acima.
Minha opinião como desenvolvedora é, sempre otimize o máximo que puder. Mas não de maneira prematura. Ou seja, pense sobre seu contexto e se for necessário alterar o conteúdo, use uma tag de layout, do contrário, use a tag fragment.
Vale considerar que o esforço para mudar de um para o outro é muito baixo. Sendo necessário apenas que o desenvolvedor detenha este conhecimento.