J'ai récemment réfléchi à cela lors de l'implémentation de account authenticators avec des flux d'autorisation à trois pattes. L'envoi d'un résultat au service pour traitement est plus efficace que le traitement dans l'activité. Cela permet également une meilleure séparation des préoccupations.
Ce n'est pas si clairement documenté, mais Android fournit un moyen facile d'envoyer et de recevoir des résultats n'importe où (y compris les services) avec ResultReceiver
. Je l'ai trouvé beaucoup plus propre que de passer des activités, car cela comporte toujours le risque de fuite de ces activités. De plus, l'appel de méthodes concrètes est moins flexible.
Pour utiliser ResultReceiver
dans un service, vous aurez besoin de sous-classe et fournir un moyen de traiter le résultat obtenu, habituellement dans une classe interne:
public class SomeService extends Service {
/**
* Code for a successful result, mirrors {@link Activity.RESULT_OK}.
*/
public static final int RESULT_OK = -1;
/**
* Key used in the intent extras for the result receiver.
*/
public static final String KEY_RECEIVER = "KEY_RECEIVER";
/**
* Key used in the result bundle for the message.
*/
public static final String KEY_MESSAGE = "KEY_MESSAGE";
// ...
/**
* Used by an activity to send a result back to our service.
*/
class MessageReceiver extends ResultReceiver {
public MessageReceiver() {
// Pass in a handler or null if you don't care about the thread
// on which your code is executed.
super(null);
}
/**
* Called when there's a result available.
*/
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Define and handle your own result codes
if (resultCode != RESULT_OK) {
return;
}
// Let's assume that a successful result includes a message.
String message = resultData.getString(KEY_MESSAGE);
// Now you can do something with it.
}
}
}
Lorsque vous démarrez une activité dans le service, créer un récepteur de résultat et de l'emballage dans les extras intention:
/**
* Starts an activity for retrieving a message.
*/
private void startMessageActivity() {
Intent intent = new Intent(this, MessageActivity.class);
// Pack the parcelable receiver into the intent extras so the
// activity can access it.
intent.putExtra(KEY_RECEIVER, new MessageReceiver());
startActivity(intent);
}
enfin, dans l'activité, déballer le récepteur et utiliser ResultReceiver#send(int, Bundle)
pour envoyer un résultat de retour.
Vous pouvez envoyer un résultat à tout moment, mais ici, j'ai choisi de le faire avant de terminer:
public class MessageActivity extends Activity {
// ...
@Override
public void finish() {
// Unpack the receiver.
ResultReceiver receiver =
getIntent().getParcelableExtra(SomeService.KEY_RECEIVER);
Bundle resultData = new Bundle();
resultData.putString(SomeService.KEY_MESSAGE, "Hello world!");
receiver.send(SomeService.RESULT_OK, resultData);
super.finish();
}
}
Il peut être réalisé avec un simple hack, par l'utilisation de SharedPreferences, [SO] (http://stackoverflow.com/a/31461941/4859873) –