2010-07-03 28 views
6

(Mi dispiace per non essere stato così chiaro nel mio primo post)MVC in Android: applicazione o servizio per aggiornamenti asincroni?

Ecco la situazione: ho dati che devono essere aggiornati da Internet. Chiamiamolo Model.

Che cosa voglio fare: Fondamentalmente suona come un modello MVC, in cui lo viene mantenuto anche nell'archiviazione locale (privata). Il Model e i suoi metodi associati sono per applicazione. Ci sono diversi Activity 's che visualizzare e manipolare diversi aspetti di essa:

  • utente naviga tra le varie Activity' s che visualizzano Model da diverse prospettive. Attualmente ho uno ListActivity per tutti gli elementi e uno Activity per i dettagli di un elemento
  • A volte è necessario aggiornare Model. Sicuramente questo è fatto su un thread diverso. Il rinfresco può essere attivato da diversi Activity.
  • Ci sono diversi (in termini di tempo) comuni compiti che possono essere attivati ​​da diverse Activity 's
  • miei carichi applicativi e salva Model all'ammasso privato quando inizia e si ferma

Il mio problema : Non sono sicuro di dove mettere Model e le attività correlate in. Inoltre, non so quale meccanismo utilizzare per notificare Activity di s. Attualmente mi vengono proposti 2 approcci:

  • Utilizzare Service e inviare trasmissioni. Il salvataggio su disco viene eseguito in Service#onDestroyed(), quindi voglio ridurlo al minimo legandolo a Activity. A questo punto, inoltre, non sono sicuro di come fornire le informazioni aggiornate: se fornire un getter in Binder o includerlo nel messaggio di trasmissione.
  • Personalizzare l'oggetto Application in modo che i metodi di aggiornamento e siano disponibili in tutto il mondo. Quindi eseguo l'aggiornamento da Activity utilizzando AsyncTask. Se ci sono altri Activity che sono dietro l'attuale Activity, si aggiorneranno in onResume() quando l'utente torna indietro.

ragioni che non sto usando una classe con metodi statici:

  • ho bisogno di salvare e archiviare Model su disco.
  • Alcuni dei metodi hanno bisogno di un contesto per la visualizzazione di brindisi, le notifiche, la cache, ecc

Inoltre, non metto queste funzionalità in un Activity, perché ci sono diverse attività che manipolano lo stesso pezzo di dati persistenti.

qui sotto sono pseudocodice che illustrano ciò che voglio dire:

Uso del servizio:

/** Service maintaining state and performing background tasks */ 
class MyService extends Service { 
    Model mModel; 
    Binder mBinder; 

    onCreate() { 
     super.onCreate(); 
     mBinder = new Binder(); 
     // load mModel from disk, or do default initialization 
    } 

    onDestroy() { 
     super.onDestroy(); 
     // save mModel to disk 
    } 

    onBind() { 
     return mBinder; 
    } 

    class Binder { 
     refresh() { 
      new AsyncTask() { 
       doInBackground() { 
        // update mModel from Internet 
       } 
       onPostExecute() { 
        sendBroadcasts(new Intent("my.package.REFRESHED")); 
       } 
      }.execute(); 
     } 

     getState() { 
      return mModel.getState(); 
     } 
    } 
} 

/** Activity displaying result */ 
class MyActivity extends ListActivity { 
    MyService.Binder mBinder; 

    onCreate() { 
     super.onCreate(); 
     // register mReceiver 
     // bind service 
    } 

    onDestroy() { 
     super.onDestroy(); 
     // unbind service 
     // unregister mReceiver 
    } 

    /** Invokes time-consuming update */ 
    refresh() { 
     // binding is asynchronous, and user may trigger refreshing too early 
     if (mBinder != null) { 
      mBinder.refresh(); 
     } 
    } 

    BroadcastReceiver mReceiver = new BroadcastReceiver() { 
     onReceive(Intent intent) { 
      if ("my.package.REFRESHED".equals(intent.getAction()) 
        && mBinder != null) { 
       updateViews(mBinder.getState()); 
      } 
     } 
    }; 
} 

Fai la funzionalità globalmente accessibile nell'oggetto Application personalizzato

/** Custom Application providing domain specific functionalities */ 
class MyApplication extends Application { 
    Model mModel; 

    onCreate() { 
     super.onCreate(); 
     // load mModel from disk, or do default initialization 
    } 

    onTerminate() { 
     super.onTerminate(); 
     // save mModel to disk 
    } 

    void refresh() { 
     /** time-consuming */ 
    } 

    getState() { 
     return mModel.getState(); 
    } 
} 

/** Activity displaying result */ 
class MyActivity extends ListActivity { 
    onResume() { 
     super.onResume(); 

     // in case some top Activities have refreshed 
     // and user is navigating back 
     updateViews(((MyApplication)getApplicationContext()).getState()); 
    } 

    /** Invokes time-consuming update */ 
    refresh() { 
     new AsyncTask() { 
      doInBackground() { 
       ((MyApplication)getApplicationContext()).refresh(); 
      } 
      onPostExecute() { 
       // update the ListView according to result 
       updateViews(((MyApplication)getApplicationContext()).getState()); 
      } 
     }.execute(); 
    } 
} 

debolezze che posso pensare per l'approazione Service ch è la complessità, poiché Binding è asincrono. Ed è molto probabile che devo ripetere qualche codice, perché ho sia ListActivity e Activity

Per l'approccio Application, la documentazione dice di non fare affidamento su onTerminate() essere chiamato.

So che sono molto imbarazzante. Qual è il modo convenzionale per risolvere questo tipo di problema?

Molte grazie.

risposta

0

Bene, è possibile estendere un BroadcastReceiver anziché un servizio, e quando ha terminato di fare ciò che deve fare, carica un'attività con i risultati.

+0

È stata colpa mia per non essere stato chiaro. Ho diverse attività che accedono e mutano lo stesso pezzo di dati applicativi :) – Phil

+0

Ho editato il mio post. Spero che non sia troppo prolisso. – Phil

0

Non hai spiegare che tipo di informazioni stai ricevendo, ma questa linea è importante:

Tali attività coinvolgono gli stati che devono per essere caricati e salvati con grazia quando si avvia l'applicazione e si ferma

Se questo è il caso, perché non si fa uno AsynTask all'interno dello Activity?

Ho avuto le stesse preoccupazioni per l'invio di Intents con ArrayList all'interno, ma ho un'app che fa esattamente questo e non ho problemi di prestazioni.

+0

Mi dispiace per non essere stato abbastanza chiaro. Non l'ho inserito in un'attività perché ho diverse attività che accedono e mutano lo stesso pezzo di dati applicativi. Ho editato il mio post. – Phil

1

Service s è particolarmente adatta per qualcosa che non è legato a un singolo Activity (e di solito collaborare con NotificationManager o un Widget). Questo non sembra essere il caso.
Quindi il mio suggerimento è quello di avere un pozzo-ingegnerizzato AsyncTask che gestisce lo stato attraverso SharedPreferences/SQLite stesso (invece di abusare Applicaion) e sarà lanciato dal ListActivity.

Problemi correlati