web-dev-qa-db-fra.com

La façon correcte d'obtenir une instance ViewModel en dehors d'une activité ou d'un fragment

Je construis une application de localisation dans laquelle j'affiche les emplacements d'arrière-plan à partir d'une base de données de pièces dans MainActivity. Je peux obtenir un ViewModel en appelant

locationViewModel = ViewModelProviders.of(this).get(LocationViewModel.class);
locationViewModel.getLocations().observe(this, this);

Les emplacements d'arrière-plan périodiques doivent être enregistrés dans la base de données de la pièce lorsque je reçois des mises à jour d'emplacement via un BroadCastReceiver. Ils devraient être sauvegardés en appelant locationViewModel.getLocations().setValue()

public class LocationUpdatesBroadcastReceiver extends BroadcastReceiver {

    static final String ACTION_PROCESS_UPDATES =
            "com.google.Android.gms.location.sample.backgroundlocationupdates.action" +
                    ".PROCESS_UPDATES";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_PROCESS_UPDATES.equals(action)) {
                LocationResult result = LocationResult.extractResult(intent);
                if (result != null) {
                    List<Location> locations = result.getLocations();
                    List<SavedLocation> locationsToSave = covertToSavedLocations(locations)
                    //Need an instance of LocationViewModel to call locationViewModel.getLocations().setValue(locationsToSave)
                }
            }
        }
    }
}

La question est de savoir comment dois-je obtenir l'instance LocationViewModel dans une classe de non-activité telle que cette BroadcastReceiver? Est-il correct d'appeler locationViewModel = ViewModelProviders.of(context).get(LocationViewModel.class) où context est le contexte que je reçois de onReceive (Context context, Intent intent) de BroadcastReceiver?

Après avoir obtenu le ViewModel, dois-je utiliser LiveData.observeForever et LiveData.removeObserver puisque BroadcastReceiver n’est pas un LifecycleOwner?

5
PrashanD

La question est de savoir comment devrais-je obtenir l'instance LocationViewModel dans une classe de Non-activité comme cette BroadcastReceiver?

Tu ne devrais pas faire ça. Sa mauvaise pratique de conception.

Est-il correct d'appeler locationViewModel = ViewModelProviders.of (context) .get (LocationViewModel.class) où Context est le contexte que je reçois de onReceive (Context context, Intent intention) du BroadcastReceiver?

Non, ça ne va pas aider

Vous pouvez obtenir le résultat souhaité comme suit:

Séparez votre opération Room DB de ViewModel dans une classe singleton distincte. Utilisez-le dans ViewModel et à tout autre endroit requis. Lorsque Broadcast est reçu, écrivez des données dans la base de données via cette classe singleton plutôt que ViewModel

Si vous observez la variable LiveData dans votre fragment, elle mettra également à jour votre point de vue.

4
Sagar

Il est anti-modèle de passer l'instance ViewModel.
Dans votre cas, transmettez plutôt locationViewModel.getLocations().
Je ne connais pas très bien les composants d'architecture, mais dans Android Data Binding, il est possible de transmettre les instances Observable* afin de définir et d'obtenir leurs valeurs. 

0
ericn