Autore Topic: [medio] MVC in Android  (Letto 11365 volte)

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
[medio] MVC in Android
« il: 07 Marzo 2010, 19:27:14 CET »
+7
Livello di difficoltà: medio
Versione SDK utilizzata: >1.5
Link al file compresso del progetto eclipse: file in allegato

Il pattern architetturale MVC è uno dei pattern più diffusi nella programmazione object oriented e nello sviluppo di interfacce grafiche.
L'MVC aumenta la coesione del nostro sistema software, in quanto la responsabilità di ogni classe viene mirata a compiti specifici.
Abbiamo un Modello dati, che come da nome, gestisce l'accesso ai dati in lettura e scrittura.
Abbiamo una View, la nostra interfaccia grafica, in android non è altro che la nostra Activity con le Views 'linkate' al file XML
Abbiamo il Controller, ovvero tutto quello che riguarda la logica che avviene dopo l'interazione con l'utente e va a modificare lo stato degli altri due componenti.

Vediamo un esempio di utilizzo di questo pattern in android:

Creiamo un semplice layout:
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <Button
                android:text="start service"
                android:id="@+id/startButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
        </Button>
        <Button
                android:text="stop service"
                android:id="@+id/stopButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
        </Button>
        <TextView
                android:id="@+id/myDataTextView"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="Premi 'start service' per iniziare"
                android:inputType="textMultiLine" />

</LinearLayout>



Model
Codice (Java): [Seleziona]
public class MyDataModel extends Observable {
       
       
        private String myData; 
        static MyDataModel singleInstance;
        // Singleton design pattern
        // usando questo pattern, siamo sicuri di avere
        // una sola istanza del nostro modello dati
        // e lo rendiamo reperibile agli utilizzatori tramite un metodo che ritorna la sua istanza
        public static MyDataModel getInstance(){
                if(singleInstance==null){
                        singleInstance=new MyDataModel();
                }
                return singleInstance;
        }

        public String getMyData() {
                return myData;
        }
       
        public void setMyData(String myData) {
                this.myData = myData;
                setChanged();
                notifyObservers();  
                // ogni volta che i dati cambiano, gli osservanti vengono informati
                // il metodo update verrà chiamato su di essi
        }

}



View
Codice (Java): [Seleziona]
public class MvcDemo extends Activity implements Observer {
    Button startButton;
    Button stopButton;
    TextView myDataTv;
    MyDataModel dataModel;
    Intent service;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setUpViews();
        dataModel=MyDataModel.getInstance();
        dataModel.addObserver(this); // aggiungiamo la nostra "View" come osservatore del modello dati
        startButton.setOnClickListener(new OnClickListener() {                 
                        @Override
                        public void onClick(View v) {
                               
                                //vogliamo complicarci la vita,
                                //invece di effettuare la modifica sui dati del modello da qui
                                //facciamo eseguire questa modifica da un servizio
                               
                                service=new Intent(getApplicationContext(), MyService.class);
                                startService(service);
                               
                        }
                });
       
        stopButton.setOnClickListener(new OnClickListener() {
                       
                        @Override
                        public void onClick(View v) {
                                if(service!=null)
                                        stopService(service); //si commenta da solo...
                               
                        }
                });
       
    }

    private void setUpViews() {
                startButton=(Button)findViewById(R.id.startButton);
                stopButton=(Button)findViewById(R.id.stopButton);
                myDataTv=(TextView)findViewById(R.id.myDataTextView);          
        }


        @Override
        public void update(Observable observable, Object data) {        //interfaccia observer 
               
                if(observable instanceof MyDataModel){
                        // in quanto potremmo avere piu modelli dati
                        // verifichiamo su quale modello è avvenuto un cambiamento dei dati
                        // prima di effettuare il cast
                        MyDataModel m=(MyDataModel)observable;
                        myDataTv.append(m.getMyData());
                }
               
        }
       
        @Override
        protected void onDestroy() {
                super.onDestroy();
                if(service!=null)
                stopService(service); // quando la nostra activity cessa di esistere, fermiamo il servizio     
        }
       
       
}



Controller
Codice (Java): [Seleziona]
public class MyService extends Service {

        MyDataModel dataModel=MyDataModel.getInstance();
        Timer timer=new Timer();
        Handler handler;
       
        @Override
        public void onStart(Intent intent, int startId) {              
                super.onStart(intent, startId);
               
                //potremmo chiamare dataModel.setMyData("\n Hello from Service");
                //direttamente qui e sarebbe tutto apposto, ma vogliamo usare un TimerTask.
                //I timertask implementano l'interfaccia Runnable
                //quindi li possiamo classificare come delle Thread.
                //come sappiamo per poter agire sulla UI da una Thread, occorre utilizzare degli Handler
               
                handler=new Handler(){
                        @Override
                        public void handleMessage(Message msg) {
                                super.handleMessage(msg);
                                dataModel.setMyData("\n Hello from Service");
                                //modifica modello dati
                        }
                };
               
               
                timer.schedule(new TimerTask() {
                       
                        @Override
                        public void run() {
                                Log.v("myService", "tic");
                                handler.sendEmptyMessage(0); //usiamo l'handler
                               
                        }
                },
                0,
                1000);
               
               
               
        }
       
        @Override
        public void onDestroy() {
                super.onDestroy();
                timer.cancel(); // una volta che il servizio viene a meno. 'puliamo' il timer
        }
       
       
        @Override
        public IBinder onBind(Intent arg0) {
                return null;
        }

}



Ovviamente per usare un servizio, il manifest va modificato di conseguenza.
Ad ogni modo, trovate il tutto in un progetto eclipse allegato.

Questo è tutto, spero che il tutorial sia di vostro gradimento  ;)


Saluti.
Qlimax


« Ultima modifica: 28 Gennaio 2011, 15:28:37 CET da Qlimax »

Offline daniele

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: +1
    • Mostra profilo
Re:[medio] MVC in Android
« Risposta #1 il: 12 Aprile 2010, 17:56:00 CEST »
0
Ottima guida, grazie.

Offline ScarfaceIII

  • Utente junior
  • **
  • Post: 112
  • Respect: +13
    • raferalston12
    • Mostra profilo
  • Dispositivo Android:
    Nexus One
  • Sistema operativo:
    GNU/Linux, Ubuntu 10.04 / Windows 7
Re:[medio] MVC in Android
« Risposta #2 il: 12 Aprile 2010, 18:57:57 CEST »
0
mi allego anche io ai ringraziamenti, ho sfruttato in maniera brutale questo tutorial per aggiungere un po' di complessità e di senso ad un'applicazione che sto sviluppando, grazie mille ;)

EDIT: ho un dubbio: l'MCV che hai riportato fa eseguire al Service una modifica al Model, ma in pratica la pressione del tasto va solamente ad avviare il servizio...poi la modifica al Model è "automatica"...fatta col timer. Se volessi attuare una modifica al Model direttamente dalla pressione del tasto (nel mio caso creare un file) dovrei farlo direttamente invocando il metodo di Model dall'Activity o dal Service? nel secondo caso, come dovrei fare? mi creo un singleInstance anche del Service nella Activity?

grazie mille
« Ultima modifica: 13 Aprile 2010, 16:59:37 CEST da ScarfaceIII »

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
Re:[medio] MVC in Android
« Risposta #3 il: 03 Maggio 2010, 17:39:58 CEST »
0
mi allego anche io ai ringraziamenti, ho sfruttato in maniera brutale questo tutorial per aggiungere un po' di complessità e di senso ad un'applicazione che sto sviluppando, grazie mille ;)

EDIT: ho un dubbio: l'MCV che hai riportato fa eseguire al Service una modifica al Model, ma in pratica la pressione del tasto va solamente ad avviare il servizio...poi la modifica al Model è "automatica"...fatta col timer. Se volessi attuare una modifica al Model direttamente dalla pressione del tasto (nel mio caso creare un file) dovrei farlo direttamente invocando il metodo di Model dall'Activity o dal Service? nel secondo caso, come dovrei fare? mi creo un singleInstance anche del Service nella Activity?

grazie mille
Ciao Scarface,
se prendiamo questo esempio, dovresti semplicemente agire all'interno dell'onclicklistener
chiamando i metodi sul modello dati.

Codice (Java): [Seleziona]
startButton.setOnClickListener(new OnClickListener() {                
                        @Override
                        public void onClick(View v) {
                               
                               
                                dataModel.setMyData("\n  Hello from Activity");
                               
                               
                        }
});


nell'esempio ho fatto modificare il model da un servizio soltanto per rendere la cosa più :P saporita :P

Saluti,
Qlimax

Offline ScarfaceIII

  • Utente junior
  • **
  • Post: 112
  • Respect: +13
    • raferalston12
    • Mostra profilo
  • Dispositivo Android:
    Nexus One
  • Sistema operativo:
    GNU/Linux, Ubuntu 10.04 / Windows 7
Re:[medio] MVC in Android
« Risposta #4 il: 04 Maggio 2010, 00:02:50 CEST »
0
Ciao, grazie mille della risposta. La mia domanda era riferita più ad un "consiglio sul corretto uso". Cioè: se l'applicazione si complica, meglio far effettuare le modifiche dal Service (e restare più coerenti con la separazione dei compiti) o direttamente dal View (semplice, evito sbattimenti...)?

P.S.:Per la cronaca: nella mia applicazione alla fine ho optato per un singleInstance del Service e nel service ho implementato il metodo per modificare il model, così Model e View si "vedono" solo attraverso l'update dell'Observed...

P.P.S.: rinnovo ancora i complimenti e i ringraziamenti per il tutorial perché essendo niubbo di Java non sapevo l'esistenza di questa possibilità ed è veramente manna dal cielo!  o_O

Offline TheTodd

  • Utente junior
  • **
  • Post: 58
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    samsung gs2
  • Play Store ID:
    sdmdev
  • Sistema operativo:
    window xp
Re:[medio] MVC in Android
« Risposta #5 il: 25 Agosto 2011, 17:20:28 CEST »
0
grazie per questo tutorial, Qlimax.
Non ho capito, però, come avviene il cambiamento di stato sulla View da parte del Controller.
Qualcuno potrebbe chiarirmi questo punto gentilmente?
« Ultima modifica: 25 Agosto 2011, 17:23:16 CEST da TheTodd »

Offline settepijo

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Re:[medio] MVC in Android
« Risposta #6 il: 05 Settembre 2011, 11:12:45 CEST »
0
Complimenti anche da parte mia.
Premessa:sto studiando da pochi giorni Android (quindi pochissima esperienza) e mi sto scegliendo un modello di programmazione da adottare per il futuro. A tal proposito valutavo l'MVC proposto (da Qlimax).


Ho però due domande (forse dettata dall'inesperienza):
1)Devo poter eseguire un Create Read Update e Delete di una o più tabelle Sqllite da un Android.
Rispettando il tuo modello come potrei distinguere le chiamate al servizio (controller) per fargli fare queste 4 operazioni?

Nell'esempio dalla view fai semplicemente "startService(service)" ed il "setMyData" lo fai nel "OnStart" del servizio quindi sempre.


2)Altra domanda:Per ogni Tabella dovrei avere sia una classe Model che una Controller?
Esempio: ImpiegatoModel e ImpiegatoController, poi altre coppie tipo RuoloModel e RuoloController, e così via....

Ti ringrazio anticipatamente.

Offline settepijo

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Re:[medio] MVC in Android
« Risposta #7 il: 13 Settembre 2011, 15:21:03 CEST »
0
niente è? non c'è nessuno.

Offline Jason88

  • Utente junior
  • **
  • Post: 73
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S
Re:[medio] MVC in Android
« Risposta #8 il: 25 Gennaio 2012, 16:16:01 CET »
0
ma se si fa una startactivityforresult() la on activity for result dove si mette???