web-dev-qa-db-fra.com

Cycle de vie de liaison de données androidx NullPointerException

Je n'arrive pas à trouver l'origine de ce DataBindingNullPointerException. En utilisant Android Navigation Architecture lors de la navigation vers un Fragment et de la remontée répétitive, je finirai par retrouver la trace de pile suivante

Java.lang.NullPointerException: Attempt to invoke direct method 'void androidx.databinding.ViewDataBinding.handleFieldChange(int, Java.lang.Object, int)' on a null object reference
        at androidx.databinding.ViewDataBinding.access$800(ViewDataBinding.Java:64)
        at androidx.databinding.ViewDataBinding$LiveDataListener.onChanged(ViewDataBinding.Java:1592)
        at androidx.lifecycle.LiveData.considerNotify(LiveData.Java:113)
        at androidx.lifecycle.LiveData.dispatchingValue(LiveData.Java:126)
        at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.Java:424)
        at androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged(LiveData.Java:376)
        at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.Java:355)
        at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.Java:293)
        at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.Java:333)
        at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.Java:138)
        at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.Java:124)
        at androidx.fragment.app.Fragment.performStart(Fragment.Java:2485)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1494)
        at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManager.Java:2646)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.Java:2416)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.Java:2372)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.Java:2273)
        at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.Java:733)
        at Android.os.Handler.handleCallback(Handler.Java:789)
        at Android.os.Handler.dispatchMessage(Handler.Java:98)
        at Android.os.Looper.loop(Looper.Java:164)
        at Android.app.ActivityThread.main(ActivityThread.Java:6938)
        at Java.lang.reflect.Method.invoke(Native Method)
        at com.Android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.Java:327)
        at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:1374)

Il semble que cela ait quelque chose à voir avec le cycle de vie LiveData comme indiqué dans l'exception. Je suppose que onPause les objets LiveData dans les ViewModel sont effacés pour la mémoire et sont ensuite pour une raison quelconque accessibles à nouveau.

Cela semble être très aléatoire car cela se produit sur tous nos fragments, mais uniquement lors de la navigation continue vers et depuis ce fragment spécifique ou entre différents fragments dans l'application. Nous n'essayons pas d'accéder aux objets LiveData après une pause/destruction du fragment. Je n'ai pas été en mesure de trouver quelqu'un qui a connu ce problème auparavant, et j'ai du mal à aller à la racine du problème.

16
Neil

J'ai rencontré ce même problème ce matin et j'étais heureux de voir que je n'étais pas le seul.

Je pense que je l'ai résolu par moi-même, mais c'est un peu difficile d'être sûr, comme vous le savez. Pour moi, c'était lors de la pagination entre les fragments d'un viewPager que j'obtenais parfois l'erreur. Je crois que les fragments se détachaient lorsqu'ils étaient hors écran, mais des mises à jour de liaison de données étaient toujours appelées. J'ai confirmé cela en définissant offscreenPageLimit du viewPager sur 0 et j'ai commencé à obtenir l'erreur de manière beaucoup plus cohérente.

Ma solution a été de remplacer:

binding.setLifecycleOwner(this);

Avec:

binding.setLifecycleOwner(getViewLifecycleOwner());

Voir: getViewLifecycleOwner

Obtenez un LifecycleOwner qui représente le cycle de vie de la vue du fragment. Dans la plupart des cas, cela reflète le cycle de vie du fragment lui-même, mais dans le cas de fragments détachés, le cycle de vie du fragment peut être considérablement plus long que le cycle de vie de la vue elle-même.

Je n'ai plus rencontré l'erreur depuis que j'ai effectué cette modification moi-même, veuillez donc me faire savoir si cela résout le problème pour vous. Je mettrai à jour ma réponse si j'obtiens enfin l'erreur à nouveau, mais jusqu'à présent, je suis convaincu que cela l'a corrigé dans mon cas.

30
Mike Simpson