0
votes

partage de données entre fragments via des viewmodels

Selon la section "Partager des données entre fragments" sur https://developer.android.com/topic/libraries/architecture/viewmodel, on nous dit que créer un ViewModel dans la portée de l'activité et le partager parmi les fragments est la voie à suivre .

C'est le fragment qui définit la valeur dans le ViewModel

class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()

    fun select(item: Item) {
        selected.value = item
    }
}

C'est le fragment de détail qui utilise le jeu de propriétés

class DetailFragment : Fragment() {

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this).get(SharedViewModel::class.java)
        } ?: throw Exception("Invalid Activity")
        model.selected.observe(this, Observer<Item> { item ->
            // Update the UI
        })
    }
}

Ceci est le ViewModel

class MasterFragment : Fragment() {

    private lateinit var itemSelector: Selector

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this).get(SharedViewModel::class.java)
        } ?: throw Exception("Invalid Activity")
        itemSelector.setOnClickListener { item ->
            // Update the UI
        }
    }
}

Ma question est simple. En supposant que MasterFragment définisse une valeur dans le ViewModel sur un clic de bouton, comment pourrions-nous récupérer cette valeur en y accédant APRÈS QUE LE SYSTÈME A TUÉ NOTRE APPLICATION ET LA RESTAURÉ?.

Notre DetailFragment ne verra pas la valeur puisque nous l'avons défini sur le bouton cliquez dans le MasterFragment. Pour mieux comprendre la question, considérons que nous avons les fragments A, B, C et D et qu'ils partagent un ViewModel qui a une valeur Fragment AB et C ensemble calculée et placée dans ViewModel pour que le fragment D y accède.

Désormais, lorsque le système tue et recrée notre application, le fragment D n'aura plus cette valeur disponible.

OnSaveInstance ne sera pas non plus en mesure d'aider beaucoup sans recourir à du code sale. Pour les situations simples, oui, mais comme celle dans laquelle FragmentA B et C ensemble font une valeur, dans cette situation, OnSaveInstance serait problématique.

OnSaveInstance aurait dû être à l'intérieur du ViewModel mais hélas je ne pense pas que ce soit le cas. Des idées?


0 commentaires

3 Réponses :


1
votes

Si vous souhaitez toujours obtenir la valeur stockée après la réinitialisation ou la suppression de l'application, vous devez enregistrer les données dans SharedPreferences ou la base de données SqLite interne et la restaurer après le démarrage de l'application.


3 commentaires

"SharedPreferences ou base de données interne SqLite" Vous êtes également autorisé à le sauvegarder en utilisant d'autres méthodes. Vous n'avez pas besoin d'utiliser l'un de ces deux


oui, il y a plus de méthodes, mais ce sont les principales et les meilleures pratiques


you need to save data to La raison you need to save data to laquelle j'ai fait le commentaire est que vous avez utilisé le mot «besoin». Vous n'avez pas BESOIN d'utiliser ces méthodes.



3
votes

Les objets ViewModel sont étendus au cycle de vie transmis au ViewModelProvider lors de l'obtention du ViewModel. Le ViewModel reste en mémoire jusqu'à ce que le cycle de vie auquel il est destiné disparaisse définitivement: dans le cas d'une activité, quand il se termine, tandis que dans le cas d'un fragment, quand il est détaché.

Tu peux le vérifier ici

Ma question est simple. En supposant que MasterFragment définisse une valeur dans le ViewModel sur un buttonClick, comment pourrions-nous récupérer cette valeur en y accédant APRÈS QUE LE SYSTÈME A TUÉ NOTRE APPLICATION ET LA RESTART?.

Vous ne pouvez pas récupérer la valeur si l'application est supprimée par l'utilisateur ou le système ou redémarrée.

Pour résoudre votre objectif d'accumuler les données des activités A, B et C et de les afficher dans l'activité D même si l'application est arrêtée ou redémarrée, vous pouvez choisir une méthode parmi les suivantes:
1. SharedPreference
2. Salle de base de données locale ou SQLite
3. Stockez les données dans un fichier

Je vous recommande d'utiliser SharedPreference pour les petites données et Room for Large and Complex data.

En un mot, ViewModel stocke les données temporairement pour survivre au changement d'orientation (pas besoin d'écrire du code de onSaveInstanceState et onRestoreInstanceState ) et de partager des données entre les activités et les fragments. Les données seront perdues si l'activité est détruite ou si le fragment est détaché.


0 commentaires

0
votes

Pour ceux qui utilisent Kotlin, essayez l'approche suivante:

  • Ajoutez les bibliothèques androidx ViewModel et LiveData à votre fichier gradle

  • Appelez votre viewmodel à l'intérieur du fragment comme ceci:

     class MainFragment : Fragment() {
    
       private lateinit var viewModel: ViewModel
    
       override fun onActivityCreated(savedInstanceState: Bundle?) {
           super.onActivityCreated(savedInstanceState)
    
           // kotlin does not have a getActivity() built in method instead we use activity, which is null-safe
           activity?.let {
               viemModel = ViewModelProvider(it).get(SharedViewModel::class.java)
           }
       }
    }
    


0 commentaires