Comment mettre à jour les informations d’une activité Android à partir d’un service d’arrière-plan

J’essaie de créer une application Android simple qui possède une liste d’activités, lorsque l’application démarre, je prévois de démarrer un service qui calculera constamment les données (elles changeront) et je veux que la ActivityList soit synchronisée avec les données que le service calcule pour la durée de vie de l’application.

Comment puis-je configurer mon activité pour qu’elle écoute le service? Est-ce la meilleure façon d’aborder ce problème?

Par exemple, si vous imaginez une liste de cours boursiers – les données seraient modifiées régulièrement et doivent être synchronisées avec le service (dans mon cas) qui calcule / récupère les données en permanence.

Merci d’avance

Comment puis-je configurer mon activité pour qu’elle écoute le service? Est-ce la meilleure façon d’aborder ce problème?

Vous avez trois options principales, comme je le vois:

  1. Vote. L’ Activity demande périodiquement au Service les dernières données. IMHO, cette option est nul, mais c’est certainement possible.

  2. Rappels. Par réponse de jax, l’ Activity enregistre un object de rappel (“observateur”) avec le Service . Le Service appelle une méthode sur le rappel lorsque les données changent, ce qui met à jour l’interface utilisateur. Vous pouvez voir un exemple d’utilisation avec un Service ici .

  3. Intents diffusion. Le Service diffuse une Intent via sendBroadcast() lors d’un changement de données. L’ Activity enregistre un BroadcastReceiver aide de registerReceiver() , et que BroadcastReceiver est averti d’une diffusion entrante. Cela déclenche l’ Activity pour charger les dernières données du Service , ou peut-être juste pour obtenir les dernières données des extras dans l’ Intent diffusion. Vous pouvez voir un exemple d’utilisation de cette technique avec un Service ici .

Cela ressemble à un bon candidat pour le modèle d’observateur. Fondamentalement, votre activité (The Observer) s’enregistrera auprès du service d’arrière-plan (The Observable) et vous pourrez envoyer ou extraire des données de votre activité. Votre observateur dans ce cas sera votre activité et l’observable sera votre service.

Si vous ne savez rien sur les motifs de conception, achetez «Head First Design Patterns», il est facile à lire et regorge d’informations utiles.

PS: je le lis maintenant.

Vous aurez un thread en arrière-plan qui calcule les modifications dans la liste. Ce thread a maintenant besoin d’une possibilité pour informer l’interface graphique que la liste a été mise à jour.

Vous pouvez utiliser une sorte de ArrayAdapter pour obtenir les données dans ListView. L’ArrayAdapter a une méthode appelée adpater.notifyDataSetChanged () chaque fois que vous appelez cette méthode, l’adaptateur verra que les données correspondantes ont changé, puis notifiera la vue de liste à mettre à jour à la prochaine possibilité.

Vous devez utiliser bindService () pour lier l’activité au service en cours d’exécution et communiquer avec elle.

 public class BindingActivity extends Activity { YourService mService; boolean mBound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to Your Service Intent intent = new Intent(this, YourService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service if (mBound) { unbindService(mConnection); mBound = false; } } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick atsortingbute) */ public void onButtonClick(View v) { if (mBound) { // Call a method from your Service. // However, if this call were something that might hang, then this request should // occur in a separate thread to avoid slowing down the activity performance. int num = mService.getRandomNumber(); Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); } } /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to the running Service, cast the IBinder and get instance LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; } 

et votre service comme:

 public class LocalService extends Service { // Binder given to clients private final IBinder mBinder = new LocalBinder(); // Random number generator private final Random mGenerator = new Random(); /** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ public class LocalBinder extends Binder { LocalService getService() { // Return this instance of LocalService so clients can call public methods return LocalService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } /** method for clients */ public int getRandomNumber() { return mGenerator.nextInt(100); } } 

Je me demande vraiment pourquoi personne n’a mentionné une approche simple utilisant un EventBus, quelle que soit la bibliothèque. C’est bien sûr si vous n’utilisez pas RX. Mon préféré est EventBus par GreenRobot. https://github.com/greenrobot/EventBus

Avec juste quelques lignes de code et aucune interface. Lancez un événement et écoutez-le où vous voulez. Il est découplé, il est thread-safe, et il ne plantera pas votre application.