116 votes

Mise à jour de l'interface utilisateur de l'activité Android à partir du service

J'ai un service qui vérifie en permanence les nouvelles tâches. S'il y a une nouvelle tâche, je veux rafraîchir l'interface utilisateur de l'activité pour afficher cette information. J'ai trouvé https://github.com/commonsguy/cw-andtutorials/tree/master/18-LocalService/ cet exemple. Est-ce une bonne approche ? D'autres exemples ?

Gracias.

5voto

Mohammed Shoeb Points 109
Callback from service to activity to update UI.
ResultReceiver receiver = new ResultReceiver(new Handler()) {
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        //process results or update UI
    }
}

Intent instructionServiceIntent = new Intent(context, InstructionService.class);
instructionServiceIntent.putExtra("receiver", receiver);
context.startService(instructionServiceIntent);

1voto

Naheel Points 362

Ma solution n'est peut-être pas la plus propre, mais elle devrait fonctionner sans problème. La logique consiste simplement à créer une variable statique pour stocker vos données sur le fichier Service et mettre à jour votre vue chaque seconde sur votre Activity .

Disons que vous avez un String sur votre Service que vous voulez l'envoyer à un TextView sur votre Activity . Cela devrait ressembler à ceci

Votre service :

public class TestService extends Service {
    public static String myString = "";
    // Do some stuff with myString

Votre activité :

public class TestActivity extends Activity {
    TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        tv = new TextView(this);
        setContentView(tv);
        update();
        Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    while (!isInterrupted()) {
                        Thread.sleep(1000);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                update();
                            }
                        });
                    }
                } catch (InterruptedException ignored) {}
            }
        };
        t.start();
        startService(new Intent(this, TestService.class));
    }
    private void update() {
        // update your interface here
        tv.setText(TestService.myString);
    }
}

0voto

usilo Points 56

Vous pouvez utiliser l'outil Android Jetpack LiveData

Conformément à la documentation :

Vous pouvez étendre une LiveData en utilisant le modèle singleton pour envelopper les services du système afin qu'ils puissent être partagés dans votre application. L'objet LiveData se connecte une fois au service système, et tout observateur ayant besoin de la ressource qui a besoin de la ressource peut simplement observer l'objet LiveData. Pour de plus amples informations, consultez Prolonger LiveData .

Voici ce que j'ai fait pour la communication entre Service et Activity et aussi Service et Fragment.

Dans cet exemple, j'ai :

  • une classe SyncLogLiveData extension de LiveData qui contient un SpannableStringBuilder
  • un service SyncService
  • un fragment SyncFragment

Le fragment "observe" les LiveData (c'est-à-dire SyncLogLiveData) et exécute une action lorsque les LiveData changent.
Les LiveData sont mises à jour par le Service.
Je pourrais également mettre à jour les LiveData du Fragment de la même manière, mais je ne le montre pas ici.

classe SyncLogLiveData

public class SyncLogLiveData extends LiveData<SpannableStringBuilder> {
    private static SyncLogLiveData sInstance;
    private final static SpannableStringBuilder log = new SpannableStringBuilder("");

    @MainThread
    public static SyncLogLiveData get() {
        if (sInstance == null) {
            sInstance = new SyncLogLiveData();
        }
        return sInstance;
    }

    private SyncLogLiveData() {
    }

    public void appendLog(String text) {
        log.append(text);
        postValue(log);
    }

    public void appendLog(Spanned text) {
        log.append(text);
        postValue(log);
    }
}

en classe SyncService

Cette ligne de code va mettre à jour le contenu de la LiveData

SyncLogLiveData.get().appendLog(message);

Vous pouvez également utiliser directement setValue(...) ou postValue(...) méthodes de LiveData

SyncLogLiveData.get().setValue(message);

classe SyncFragment

public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {

    //...

    // Create the observer which updates the UI.
    final Observer<SpannableStringBuilder> ETAObserver = new Observer<SpannableStringBuilder>() {
        @Override
        public void onChanged(@Nullable final SpannableStringBuilder spannableLog) {
            // Update the UI, in this case, a TextView.
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    textViewLog.setText(spannableLog);
                }
            });
        }
    };
    // Observe the LiveData, passing in this activity/fragment as the LifecycleOwner and the observer.
    SyncLogLiveData.get().observe(getViewLifecycleOwner(), ETAObserver);

    //...
}

À l'intérieur d'une activité, cela fonctionne de la même manière, mais pour les éléments suivants .observe(...) vous pouvez utiliser ceci à la place

SyncLogLiveData.get().observe(this, ETAObserver);

Vous pouvez également récupérer la valeur actuelle des LiveData de cette manière à tout moment dans votre code.

SyncLogLiveData.get().getValue();

J'espère que cela pourra aider quelqu'un. Il n'a pas encore été question de LiveData dans cette réponse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X