• Programmazione Android
  • CORSI ONLINE
  • Web Agency

Logo

Corsi di programmazione web e mobile online
Navigation
  • Home
  • CORSI ONLINE
  • Tutorial Pratici
  • GUIDE COMPLETE
    • Corso completo di C
    • Corso videogame con Cocos2d
    • Programmazione Cocoa Touch
  • Sezioni
    • Libri e manuali
    • Tips & Tricks
    • Risorse utili
    • Strumenti di Sviluppo
    • Materiale OpenSource
    • Framework
    • Guide Teoriche
    • Guide varie
    • Grafica e Design
    • iPad
    • News
    • Video Tutorial
    • Windows Phone
  • Pubblicità
  • About
    • Chi siamo
    • Pubblicazioni
    • Collabora
    • Sostieni devAPP

Android Fragments: sperimentiamo il ciclo di vita

By Giuseppe Maggi | on 21 Maggio 2018 | 0 Comment
Android

I Fragments, come abbiamo già ricordato, sono una caratteristica potente di Android per la creazione di interfacce utente dinamiche e riutilizzabili ma spesso nascondono delle insidie. Buona parte di queste trappole si celano nel ciclo di vita, articolato ma non difficile da padroneggiare se approcciato con la necessaria cura: di questo tratta il nostro post.

Le fasi del ciclo di vita

Il diagramma che segue mostra le fasi del ciclo di vita di un Fragment messe a confronto con quelle dell’Activity:

 

Quello che è mostrato è tutta l’esistenza di un Fragment da quando è collegato all’interfaccia a quando viene (eventualmente) distrutto.Al centro (tra i metodi onResume e onPause) si inserisce la fase running, l’interazione con l’utente.

Un fragment può esistere solo all’interno di una Activity per questo il ciclo di vita dell’uno e dell’altra si innestano.

Un’Activity, da quando viene creata a quando diventa running, passa per tre metodi di callback (onCreate, onStart, onResume) e, se contiene fragments, la creazione della sua interfaccia utente consiste proprio nell’istanziazione di questi. I cicli di vita andranno di pari passo: parallelamente, anche il fragment invocherà onCreate, onStart, onResume. La differenza rispetto all’Activity è che il fragment invoca altri suoi metodi specifici:

  • onAttach: segna il momento in cui il fragment è collegato all’Activity, questa  viene passata al metodo come Context. E’ il punto ideale per salvare un riferimento al Context valido da usare durante la vita del Fragment;
  • onCreateView: viene qui prodotto il layout dell’interfaccia che verrà restituito. Tra i parametri in ingresso riceve un LayoutInflater che servirà proprio all’elaborazione di un layout XML;
  • onActivityCreated annuncia che la creazione dell’Activity è completa, da questo momento in poi il Fragment potrà interagire con essa.

Quando un’Activity smette di interagire con l’utente verrà invocato onPause, quando non è più visibile onStop fino alla sua (eventuale) distruzione che verrà segnalata da onDestroy. I metodi omonimi dei fragment hanno gli stessi ruoli mentre i due specifici onDestroyView e onDetach segnalano, rispettivamente, la rimozione dell’interfaccia utente e lo scollegamento dall’Activity.

L’esempio

L’esempio che presentiamo ha la finalità principale di stimolare la riflessione sul ciclo di vita dei Fragments. Abbiamo un’Activity contenente due Fragments.

Il primo Fragment ha nell’interfaccia un pulsante che serve ad aprire il secondo:

Il secondo Fragment mostra un contatore numerico ed un pulsante che serve per tornare al primo.

Ogni volta che viene aperto il secondo Fragment il contatore viene incrementato di uno: su questo verte buona parte dell’esempio in quanto solo il corretto riutilizzo dei Fragment permetterà al contatore di essere incrementato e di non ri-inizializzarsi ogni volta mostrando sempre il numero 1.

Il codice

I Fragment si alterneranno in un FrameLayout che costituisce il layout dell’Activity:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Nel metodo onCreate dell’Activity viene caricato il layout e con la FragmentTransaction viene aggiunto il primo Fragment:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.activity_main, new MainFragment(), MainFragment.TAG)
                .commit();
    }

Il codice del primo Fragment è molto semplice, crea solo l’interfaccia in onCreateView. Se non sono richieste funzionalità particolari, ciò può bastare anche in Fragment più complessi:

public class MainFragment extends Fragment {

    public final static String TAG="LC_PRIMO_FRAGMENT";

    public MainFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_main, container, false);
    }

}

Il layout del primo Fragment contiene un solo pulsante:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Passa al secondo Fragment"
        android:onClick="passaAlSecondo"/>

</RelativeLayout>

il suo click invocherà il metodo passaAlSecondo dell’Activity:

public void passaAlSecondo(View v)
    {
        SecondFragment sf= (SecondFragment) getSupportFragmentManager().findFragmentByTag(SecondFragment.TAG);
        if (sf==null)
            sf=new SecondFragment();

        getSupportFragmentManager()
                .beginTransaction()
                .addToBackStack(null)
                .replace(R.id.activity_main, sf, SecondFragment.TAG)
                .commit();
    }

Piuttosto che crearlo da zero, prima verifichiamo se un’istanza del secondo fragment è conservata nel FragmentManager. Lo possiamo riconoscere dal TAG associatogli durante il replace della FragmentTransaction.

ll SecondFragment ha un layout che non stupisce (file /res/layout/fragment_second.xml):

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:layout_centerInParent="true"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0"
            android:layout_gravity="center_horizontal"
            android:textStyle="bold"
            android:textSize="25sp"
            android:id="@+id/conteggio"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:onClick="tornaAlPrimo"
            android:text="Torna al primo Fragment" />

    </LinearLayout>


</RelativeLayout>

e nella classe Java che lo rappresenta definiamo il layout in onCreateView mentre in onResume incrementiamo la variabile che tiene il conto delle visualizzazioni e ne inserisce il valore nella TextView.

public class SecondFragment extends Fragment {

    public final static String TAG="LC_SECONDO_FRAGMENT";

    private Integer conta=0;

    public SecondFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_second, container, false);
    }

    @Override
    public void onResume() {
        super.onResume();
        TextView txt= (TextView) getView().findViewById(R.id.conteggio);
        conta++;
        txt.setText(conta.toString());
    }
}

Senza riciclare il Fragment, il conteggio ripartirebbe sempre da zero, non mostrando mai incrementi.

Cliccando il pulsante presente nel secondo fragment viene invocato il metodo tornaAlPrimo dell’Activity:

public void tornaAlPrimo(View v)
    {
        MainFragment sf= (MainFragment) getSupportFragmentManager().findFragmentByTag(MainFragment.TAG);
        if (sf==null)
            sf=new MainFragment();
        getSupportFragmentManager()
                .beginTransaction()
                .addToBackStack(null)
                .replace(R.id.activity_main, sf, MainFragment.TAG)
                .commit();
    }

Anche in questo caso tentiamo di riciclare il Fragment già usato (anche se non si devono conservare dati è comunque una buona prassi) e poi eseguiamo il replace nella FragmentTransaction. Notare che visto che la transazione con cui viene caricato il secondo fragment è caricato nel BackStack sarebbe stato sufficiente in questo metodo chiamare popBackStack che inverte l’ultima transazione eseguita. Ciò però comporterebbe che il Fragment dismesso (il secondo in questo caso) verrebbe del tutto distrutto fino alla chiamata del metodo onDetach: la conseguenza sarebbe una creazione da zero alla riapertura del secondo fragment con il conteggio che ricomincerebbe.

Ricapitolando…

In questo articolo, abbiamo visto il ciclo di vita dei Fragments ma non ci siamo limitati a elencare le fasi che lo compongono. L’esempio che abbiamo trattato utilizza l’espediente del conteggio allo scopo di invitare il programmatore al riciclo dei Fragments. Come è stato svolto – utilizzando sempre replace nonchè l’impiego dei tag per il recupero di Fragment già creati ma evitando l’uso di popBackStack  – il ciclo di vita nella fase che segue il running non va mai oltre il metodo onDestroyView, smantellando quindi l’interfaccia utente ma senza distruggere il componente. Conseguenza di ciò, al momento di ripristinare un fragment già visitato non ripartiamo da onAttach bensì da onCreateView ed il nostro conteggio sarà salvo.

I Fragment vanno usati con accortezza, solo in questo modo potremo sprigionare le loro potenzialità senza incappare in errori: la tematica è interessante e piena di implicazioni, non finiremo certo qui di trattarla.

Alla prossima!

Share this story:
  • tweet

Tags: androiddesign user interface androidfragmetsTutorial Pratici

Recent Posts

  • Parte il percorso programmatori iOS in Swift su devACADEMY.it

    20 Dicembre 2017 - 0 Comment
  • Android, crittografare dati velocemente con Encryption

    24 Settembre 2018 - 0 Comment
  • Sql2o, accesso immediato ai database tramite Java

    3 Settembre 2018 - 0 Comment
  • Okio, libreria per ottimizzare l’input/output in Java

    27 Agosto 2018 - 0 Comment

Related Posts

  • IntelliJ IDEA: IDE per programmare in Java e Kotlin

    25 Luglio 2018 - 0 Comment
  • Android: usare Connect Pattern

    10 Luglio 2018 - 0 Comment
  • Android: il metodo findViewById() non richiede più il cast

    21 Giugno 2018 - 0 Comment

Author Description

No Responses to “Android Fragments: sperimentiamo il ciclo di vita”

Leave a Reply

Your email address will not be published. Required fields are marked *


*
*

Corso online di programmazione android e java

SEZIONI

  • Android
  • Comunicazioni
  • Contest
  • Corsi ed Eventi
  • Corso completo di C
  • Corso programmazione videogiochi
  • Framework
  • Grafica e Design
  • Guida rapida alla programmazione Cocoa Touch
  • Guide Teoriche
  • Guide varie
  • iPad
  • Le nostre applicazioni
  • Libri e manuali
  • Materiale OpenSource
  • News
  • Pillole di C++
  • Progetti completi
  • Risorse utili
  • Strumenti di Sviluppo
  • Swift
  • Tips & Tricks
  • Tutorial Pratici
  • Video Tutorial
  • Windows Phone

Siti Amici

  • Adrirobot
  • Allmobileworld
  • Apple Notizie
  • Apple Tribù
  • Avvocato360
  • Blog informatico 360°
  • bubi devs
  • fotogriPhone
  • GiovaTech
  • iApp-Mac
  • iOS Developer Program
  • iPodMania
  • MelaRumors
  • Meritocracy
  • SoloTablet
  • TecnoUser
  • Privacy & Cookie Policy
©2009-2018 devAPP - All Rights Reserved | Contattaci
devAPP.it è un progetto di DEVAPP S.R.L. - Web & Mobile Agency di Torino
Str. Volpiano, 54 - 10040 Leini (TO) - C.F. e P.IVA 11263180017 - REA TO1199665 - Cap. Soc. € 10.000,00 i.v.

devACADEMY.it

Vuoi imparare a programmare?

Iscriviti e accedi a TUTTI i corsi con un’unica iscrizione.
Oltre 70 corsi e migliaia di videolezioni online e in italiano a tua disposizione.

ISCRIVITI SUBITO