Corso Programmazione Android Lezione 2: Descrizione App, Activity e analisi codice
Le altre lezioni del Corso di Programmazione Android sono reperibili a questo indirizzo
Dopo aver installato l’ambiente di sviluppo è ora di passare all’azione, ma prima un po di teoria.
Descrizione dell’applicazione
Dopo attenta riflessione ho finalmente avuto un’idea per un’App semplice ma anche utile.
L’idea mi è venuta quando mi è stato portato in ufficio da una collega un libro che sapevo di avere ma che non ricordavo assolutamente di aver prestato. Pur essendomi convertito da qualche anno agli ebook ho tantissimi libri, ma per motivi di spazio gli ho divisi fra casa mia, casa dei suoceri e casa dei miei. Mettendo a posto il libro mi sono anche accorto di aver prestato la Guida Galattica per Autostoppisti, ma non ricordo assolutamente a chi (orroreeee).
Quindi ho deciso che urge un’App in grado di gestire le nostre collezioni (libri, dischi, fumetti, ecc.) con relativo prestito.
Possiamo così approfondire diversi argomenti fra i quali i database.
Teoria
Activity
Ogni applicazione che si rispetti è formata da schermate, sia un’applicazione mobile che un’applicazione desktop, Android chiama le schermate Activity. Ogni activity viene gestita tramite classe Java che estende Activity (o una delle sue derivate), dobbiamo abituarci a sviluppare Activity per Activity.
Ogni Activity ha il suo file XML (o più) contenente tutti i dati necessari per il disegno della schermata.
Ciclo di vita di una Activity
Come ogni corso Android che si rispetti riportiamo lo schema relativo al ciclo di vita delle Activity
Urge un piccola spiegazione. Come detto, ogni Activity ha una propria classe Java ma, differentemente da un’applicazione Java “normale”, nessuna delle classi conterrà il metodo main(). L’avvio e l’arresto dell’Activity (sia per chiusura che per passaggio ad altra activity/dialog) vengono gestiti direttamente da Android richiamando direttamente alcuni metodi di callback.
I metodi di callback, riportati nello schema, sono:
- onCreate(): creazione. L’argomento savedInstanceState serve per riportare un eventuale stato dell’attività salvato in precedenza da un’altra istanza che è stata terminata. L’argomento è null nel caso in cui l’attività non abbia uno stato salvato.
- onRestart(): riavvio dell’activity precedentemente arrestata.
- onStart(): l’attività sta per diventare visibile sullo schermo
- onResume(): sta per iniziare l’interazione con l’utente
- onPause(): non sta più interagendo con l’utente
- onStop(): non è più visibile sullo schermo.
- onDestroy(): l’activity sta per essere terminata
Come vedremo più sotto studiando il codice autogenerato da Android Studio, non tutti i metodi di callback devono essere implementati (essendo già definiti dalla classe Activity). In caso di implementazione devono riportare @Override.
Quando da un’Activity ne richiameremo un’altra Android invocherà il metodo onPause() e al momento che tornerà visibile sarà richiamato onRestart().
Pratica
Apriamo Android Studio e prepariamoci a creare un nuovo progetto.
Ho deciso che la nostra App si chiamerà BeReader, come company name (e quindi come nomepackage) mettiamo il nostro sito (o quello che volete)
Vogliamo un’App funzionante con il 70% dei device (non wearable) quindi usiamo come minimum SDK Android 4.4 (API 19).
Nota: l’app è stata aggiornata ed essendo calata drasticamente la quota di Android 4.4 ho deciso di usare Android 5.0 come minimum SDK dalla versione 1.2.
Selezioniamo la creazione di una Blank Activity (quindi vuota) e lasciamo inalterato il resto.
Android Studio ci fa attendere un po’ ma crea e compila il nostro progetto, già perfettamente funzionante.
Una volta eseguita la nostra App si presenta così (per eseguire usiamo Run nella barra degli strumenti (ha la forma di un “play” di colore verde):
Composizione del progetto
Android Studio ha creato per noi un progetto standard, il classico “Hello World”.
Un progetto standard ha la seguente struttura:
Come è ovvio la cartella java contiene le classi, la cartella layout contiene gli XML che servono al disegno delle Activity, la cartella values contiene file vari come le stringhe e gli stili.
Analizziamo il codice
Lo so che mi fareste scannare pur di analizzare il codice, visto che odio il sangue, sopratutto se è mio, procediamo:
public class MainActivity extends AppCompatActivity {
La nostra App per ora consta di una sola Activity nominata MainActivity che estende AppCompatActivity. AppCompatActivity (che a sua volta estende Activity) è un tipo di Activity specifico da utilizzare se vogliamo accedere ai componenti Material Design anche su versioni di Android inferiori alla 5.0.
La classe contiene tre metodi, ma per ora ci occuperemo solo di onCreate()
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); }
Con questo metodo riscriviamo (@Override) il metodo di callback richiamato appena l’activity viene creata. Come argomento passiamo lo stato.
Per prima cosa richiamiamo il metodo originale (usando super come per ogni metodo Java):
super.onCreate(savedInstanceState);
Poi richiamiamo il layout (non preoccupatevi vedremo dopo cosa abbiamo richiamato)
setContentView(R.layout.activity_main);
Definiamo un’istanza della classe Toolbar così da poterci interagire e associarli un l’id dal layout. La toolbar è la banda blu in alto con il titolo dell’applicazione e il menù.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar);
Poi ci occupiamo del pulsante FAB (bel nome vero?) cioè Floating Action Button, quindi il pulsante rotondo in basso a destra.
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } });
Abbiamo definito un’istanza, associato un id e definito il comportamento al momento del click. Per definire il comportamento abbiamo creato una classe interna anonima, una funzionalità di Java molto usata in ambiente Android. Al momento del click sul pulsante FAB ci viene mostrato un messaggio in basso.
Gli altri due metodi gestiscono in menù ma per ora li tralasciamo.
Analizziamo il layout
I layout si trovamo sotto res/layout/ e nello specifico abbiamo usato il file activity_main.xml, analizziamolo. All’apertura del file Android Studio ci viene mostra la scheda Design, clicchiamo sulla scheda Text per poter vedere il sorgente.
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.begeekmyfriend.bereader.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>
Questo codice è più complesso e lo analizzeremo nel dettaglio nelle prossime lezioni, per ora vediamolo per sommi capi.
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.begeekmyfriend.bereader.MainActivity">
Creiamo un layout CoordinatorLayout (compatibile con tutte le versioni di Android) e gli diciamo di prendersi tutto lo spazio disponibile sullo schermo.
<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout>
Definiamo un componente AppBarLayout gli diciamo di prendersi tutto lo spazio messo a disposizione dal contenitore (CoordinatorLayout) in larghezza e di utilizzare solo lo spazio che gli serve in altezza. Gli diciamo anche di usare uno stile specifico. Al suo interno inseriamo un componente Toolbar con id toolbar (vedi classe) definiamo l’altezza (usando una costante) e i colori (sempre usando una costante)
<include layout="@layout/content_main" />
Includiamo alcuni componenti da un file separato (la leggibilità del codice effettivamente è migliore).
<android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" />
Definiamo il tasto FAB, associando un id (vedi classe) , lo mettiamo in basso a destra e gli diamo un icona
Abbiamo detto che alcuni componenti sono su un file separato vediamolo
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.begeekmyfriend.bereader.MainActivity" tools:showIn="@layout/activity_main"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </RelativeLayout>
Qui definiamo un RelativeLayout (non preoccupatevi vedremo i tipi di layout prossimamente) e ci inseriamo dentro una casella di testo dove scriviamo Hello world!
Per adesso abbiamo finito (era l’ora mi sono annoiato da solo) nella prossima lezione vedremo i file all’interno della cartella res/values e inizieremo a modificare qualcosa.
Originariamente pubblicato su Be Geek My Friend