Comment récupérer les résultats d’un IntentService dans une activité?

J’utilise un IntentService pour gérer les communications réseau avec un serveur via JSON. La partie JSON / serveur fonctionne correctement, mais j’ai du mal à récupérer les résultats là où ils sont nécessaires. Le code suivant montre comment je lance le service d’intention à partir de onClick (), puis demande au service de mettre à jour une variable globale pour relayer les résultats à l’activité principale.

public class GXActivity extends Activity { private static final Ssortingng TAG = "GXActivity"; @Override public void onCreate(Bundle savedInstanceState) { // === called when the activity is first created Log.i(TAG, "GXActivity Created"); super.onCreate(savedInstanceState); setContentView(R.layout.start); View.OnClickListener handler = new View.OnClickListener() { public void onClick(View v) { // === set up an application context to hold a global variable // === called user, to contain results from the intent service GXApp appState = ((GXApp) getApplicationContext()); User user = new User(-1); // initialize user id to -1 appState.setUser(user); // === next start an intent service to get JSON from the server; // === this service updates the user global variable with // === results from the JSON transaction Intent intent = new Intent(this, GXIntentService.class); startService(intent); // === check app context for results from intent service appState = ((GXApp) getApplicationContext()); if (appState.getUser().getId() != -1)... } } } } 

Le problème que j’ai est que le service d’intention qui parsing le JSON n’est pas appelé tant que onCreate () n’est pas terminé, donc mon code qui recherche les résultats est bloqué à la recherche des résultats non initialisés.

Que dois-je faire différemment afin que le service d’intention soit appelé avant que je vérifie les résultats? Est-ce que cela fonctionnerait si je retirais le programme d’écoute de la fonction onCreate ()? Y a-t-il un autre / meilleur pour structurer ce code? Merci beaucoup.

Vous devriez envisager de créer votre propre sous-classe ResultReceiver dans votre activité. ResultReceiver implémentations de Parcelable peuvent être transmises de votre Activity à votre Service tant que complément à l’ Intent .

Vous devrez faire quelque chose comme ceci:

  1. Implémentez une sous-classe de ResultReceiver dans votre classe d’activité. La méthode clé à implémenter est onReceiveResult() . Cette méthode vous offre un dataset de résultat pouvant être utilisées pour transmettre les informations que vous récupérez dans votre Service . Déballez simplement les données dont vous avez besoin et utilisez-les pour mettre à jour votre activité.

  2. Dans votre activité, créez une nouvelle instance de votre ResultReceiver personnalisé et ajoutez-la à l’ Intent vous utilisez pour démarrer votre service.

  3. Dans la méthode onStartCommand() votre Service , récupérez le ResultReceiver transmis sur Intent et stockez-le dans une variable membre locale.

  4. Une fois que votre Service terminé son travail, demandez-lui d’ send() sur le ResultReceiver en transmettant les données que vous souhaitez renvoyer à l’activité dans un Bundle .

Ceci est un modèle assez efficace et signifie que vous ne stockez pas de données dans des variables statiques désagréables.

Il y a plusieurs façons de faire des choses en arrière-plan pour récupérer un résultat (AsyncTask, lier une Activity à un Service …), mais si vous voulez conserver votre code IntentService, vous pouvez simplement:

1- envoyer une intention de diffusion (qui contient le statut dans ses données étendues) à la fin du travail dans votre IntentService

2- implémenter un LocalBroadcastReceiver dans votre activité qui consum les données de l’intention

C’est également la méthode recommandée dans la documentation officielle (si vous souhaitez conserver votre IntentService):

https://developer.android.com/training/run-background-service/report-status.html

Si tout ce que vous avez à faire est d’obtenir un JSON du serveur sans verrouiller le thread de l’interface utilisateur, il peut être plus simple d’utiliser AsyncTask .

Vous pouvez utiliser la bibliothèque Otto . Otto est un projet Open Source conçu pour fournir une implémentation de bus d’événements afin que les composants puissent publier et s’abonner à des événements.