web-dev-qa-db-fra.com

Comment mettre à jour des informations dans une activité Android à partir d'un service en arrière-plan

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

Comment puis-je configurer mon activité pour être à l'écoute du 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

39
rhinds

Comment puis-je configurer mon activité pour être écouter le service? Est-ce le meilleure façon d'aborder ce problème?

Vous avez trois options principales, comme je le vois:

  1. Vote. La Activity demande périodiquement à la Service les dernières données. IMHO, cette option est nulle, mais c'est certainement possible.

  2. Rappels. Selon la réponse de jax, la variable Activity enregistre un objet de rappel ("observateur") avec la variable Service. La Service appelle une méthode sur le rappel lorsque les données sont modifiées, ce qui met à jour l'interface utilisateur. Vous pouvez voir un exemple d'utilisation de cela avec une variable Servicehere .

  3. Broadcast Intents. La Service diffuse une Intent via sendBroadcast() sur un changement de données. La Activity enregistre une BroadcastReceiver en utilisant registerReceiver(), et cette BroadcastReceiver est avertie d'une diffusion entrante. Ceci déclenche la Activity pour charger les dernières données de la Service, ou éventuellement simplement pour extraire les dernières données des extras de la diffusion Intent. Vous pouvez voir un exemple d'utilisation de cette technique avec un Serviceici .

94
CommonsWare

Cela semble être un bon candidat pour le modèle Observer. Fondamentalement, votre activité (The Observer) s’enregistrera elle-même auprès du service d’arrière-plan (The Observable) et vous pourrez alors pousser ou extraire des données de votre activité. Dans ce cas, votre observateur sera votre activité et l'observable sera votre service.

Si vous ne connaissez rien aux modèles de conception, achetez "Head First Design Patterns", il est facile à lire et regorge d'informations de qualité.

PS: Je le lis maintenant.

4
jax

Je me demande vraiment pourquoi personne ne mentionne une approche simple utilisant un EventBus de quelque bibliothèque que ce soit. Ceci est bien sûr si vous n'utilisez pas RX. Mon préféré est EventBus de GreenRobot . https://github.com/greenrobot/EventBus

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

1
miroslavign

Vous aurez un thread en arrière-plan en cours d'exécution qui calcule les modifications dans la liste. Ce fil doit maintenant avoir la possibilité d’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. 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 été modifiées, puis notifiera au listview qu'il doit être mis à jour à la prochaine occasion. 

0
Janusz

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 attribute) */
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);
  }
}
0
Arun kumar