web-dev-qa-db-fra.com

Android - onAttach (Context) non appelé pour API 23

J'ai mis à jour le SDK avec la dernière version (API 23) et la méthode onAttach(Activity) pour fragment est obsolète. Donc, au lieu d’utiliser cette méthode, j’utilise maintenant onAttach(Context) mais celle-ci n’est pas appelée pendant le cycle de vie. L'activité est une instance de AppCompatActivity de la v7 et le fragment est une instance de la classe Fragment (Android.app.Fragment).

Des idées sur la manière de faire fonctionner la onAttach dans API 23?

Solution

J'ai trouvé des réponses qui peuvent vous aider à comprendre et à résoudre ce problème: 

  • Comme je l’ai déjà mentionné, j’utilise l’activité de support v7 (AppCompatActivity) et le fragment d’Android.app. 

  • Pour afficher des fragments, je reçois le gestionnaire de fragments à l'aide de la méthode getFragmentManager sur l'activité. Le gestionnaire de fragments est donc une instance de FragmentManager à partir d'Android.app -> et voici le problème.

  • Si vous exécutez l’application sur un périphérique doté de l’API 23 (je l’ai exécutée sur AS Emulator), vous verrez que la méthode onAttach (Context) sera appelée. Pendant le processus d'affichage d'un fragment par FragmentManager, la méthode onAttach (..) est appelée à un moment donné. En utilisant getFragmentManager (), vous obtiendrez une instance du gestionnaire de fragments disponible pour la version Android qui s'exécute sur ce périphérique (par exemple, les API 22, 23). Si l'application est exécutée sur un périphérique avec une API <23, la méthode onAttach (Context) n'est pas disponible, le gestionnaire de fragments ignore que dans l'API 23, il existe une méthode onAttach (Context), c'est pourquoi elle n'est pas appelée. pour l'API <23 ->, la solution à ce type de problèmes consiste à utiliser FragmentManager à partir de bibliothèques de support. 

  • Solutions: 

    1. Utiliser getSupportFragmentManager () vous obligera à utiliser un fragment de la bibliothèque de support. La première solution consiste donc à remplacer tous les fragments par le fragment de support lib et à l'aide de getSupportFragmentManager ().

    2. La solution que j'ai déjà implémentée consiste à gérer 2 possibilités (1. L'application s'exécute sur un périphérique avec une API <23, l'application s'exécute sur un périphérique avec une API> = 23).

    Bientôt, dans mon implémentation, j'ai une classe de base pour tous les fragments du projet et j'ai ajouté ce code là:

    /*
     * onAttach(Context) is not called on pre API 23 versions of Android and onAttach(Activity) is deprecated
     * Use onAttachToContext instead
     */
    @TargetApi(23)
    @Override
    public final void onAttach(Context context) {
        super.onAttach(context);
        onAttachToContext(context);
    }
    
    /*
     * Deprecated on API 23
     * Use onAttachToContext instead
     */
    @SuppressWarnings("deprecation")
    @Override
    public final void onAttach(Activity activity) {
        super.onAttach(activity);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            onAttachToContext(activity);
        }
    }
    
    /*
     * Called when the fragment attaches to the context
     */
    protected void onAttachToContext(Context context) {
    }
    

    Maintenant, je remplace simplement la méthode onAttachToContext (Context) sur tous les fragments pour lesquels j'ai besoin de cela. 

    69
    David Rauca

    J'ai résolu le problème de cette façon:

    @TargetApi(23)
    @Override public void onAttach(Context context) {
        //This method avoid to call super.onAttach(context) if I'm not using api 23 or more
        //if (Build.VERSION.SDK_INT >= 23) {
            super.onAttach(context);
            onAttachToContext(context);
        //}
    }
    
    /*
     * Deprecated on API 23
     * Use onAttachToContext instead
     */
    @SuppressWarnings("deprecation")
    @Override public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (Build.VERSION.SDK_INT < 23) {
            onAttachToContext(activity);
        }
    }
    
    /*
     * This method will be called from one of the two previous method
     */
    protected void onAttachToContext(Context context) {}
    
    26
    Francesco Florio

    Vous devriez essayer d'utiliser la version de la bibliothèque de support de Fragment.

    Vous devez passer à import Android.support.v4.app.Fragment; au lieu de import Android.app.Fragment;. Vous devrez également vous assurer que vous utilisez getSupportFragmentManager() au lieu de getFragmentManager().

    17
    Jellibus Bellibean

    Je suis venu avec le même problème ... J'ai un minSdkVersion de 19 et un targetSdkVersion de 23 et j'utilise fragmentManager dans un AppCompatActivity. 

    onAttach(Activity activity) est marqué comme obsolète, mais j'ai rencontré des problèmes d'application lorsque je l'ai remplacé par onAttach(Context context).

    Donc, au lieu de cela, j’ai maintenant les deux versions présentes} et lorsque je lance mon application sur API22, onAttach(Activity activity)est déclenché, même s’il est marqué comme obsolète.

    Je ne l’ai pas testé sur un appareil Android Marshmallow, mais j’ai bien compris qu’il exécuterait la version onAttach(Context context) en ignorant l’autre.

    Update à prendre en compte l'observation de @ skaar dans les commentaires ci-dessous: Je peux maintenant tester sur API23 et confirmer que l'exécution sur la plate-forme 23 entraîne l'utilisation des deux méthodes (avec Activity et Context) être appelé. Merci pour l'information!

    4
    0x4e84

    plays post sur ce bogue ici 

    NUMÉRO OUVERT SUR LE PROJET GOOGLE AOSP HOMESITE:

    https://code.google.com/p/Android/issues/detail?id=185465

    ps. ce n'est pas à vous de chercher une solution à ce problème et de trouver des solutions de contournement .. mais de forcer Google à réparer son API endommagée! Pour faire cela, vous devez vous plaindre comme je l’ai dit.

    problème lié - getContext () from fragment:

    https://code.google.com/p/Android/issues/detail?id=185848

    4
    ceph3us

    Après avoir lu votre réponse @ David Rauca .__, je pense que le second peut résoudre mon problème. Mais quand je regarde dans le code source. J'ai trouvé qu'en fait, onAttach(Context context) ne fait rien sur Android M, vient d'appeler l'ancienne méthode.

    En solution:

    @SuppressWarnings("deprecation")
    

    Il suffit de l’ajouter à l’ancienne méthode, c’est la meilleure solution.

    3
    Tony Zhang

    J'ai rencontré le même problème… .. Ce que j'ai fait pour le résoudre:

    1. Modifiez le type d'argument de rappel onAttach de Activity à Context . Pour une raison inconnue, cette modification entraîne le fait que la méthode OnAttach (Context) n'est pas appelée plus au cours du cycle de vie du fragment. En conséquence, mon application se bloquait car le code qui était dans la méthode onAttach N'avait jamais été exécuté. 

    2. Déplacez le code qui était dans la méthode onAttach vers onCreate one depuis sa est toujours exécuté.

    Avec cette modification, l'application tourne pour fonctionner comme avant. Aucune autre déclaration import n'était requise.

    2
    Andrew
    @Override
    public void onAttach(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            super.onAttach(context);
            onAttachToContext(context);
        } else {
            Activity activity = getActivity();
            super.onAttach(activity);
            onAttachToContext(activity);
        }
    }
    
    0
    Name Surname