web-dev-qa-db-fra.com

Android Fragment onAttach () obsolète

J'ai mis à jour mon application pour utiliser la dernière bibliothèque de support technique (version 23.0.0). J'ai découvert qu'elle dépréciait la fonction onAttach () de la classe Fragment.

Au lieu de:

onAttach (Activity activity)

La neige:

onAttach (Context context)

Comme mon application utilise l'activité passée avant la dépréciation, une solution possible est:

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    activity = getActivity();
}

Serait-ce la bonne façon de le faire?

UPDATE:

Si je lance un appareil avec une API inférieure à 23, le nouveau onAttach () n'est même pas appelé. J'espère que ce n'est pas ce qu'ils avaient l'intention de faire!

UPDATE 2:

Le problème a été résolu avec les dernières mises à jour du SDK.

J'ai testé sur mon périphérique API 22 et onAttach (Context) est appelé.

Cliquez ici pour suivre le rapport de bogue que j'ai ouvert il y a quelques semaines et les réponses des gars de Google.

309
TareK Khoury

L'activité est un contexte, donc si vous pouvez simplement vérifier que le contexte est une activité et le lancer si nécessaire.

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    Activity a;

    if (context instanceof Activity){
        a=(Activity) context;
    }

}

Mise à jour: Certains affirment que la nouvelle substitution Context n'est jamais appelée. J'ai fait des tests et je ne trouve pas de scénario qui confirme cela et selon le code source, cela ne devrait jamais être vrai. Dans tous les cas que j'ai testés, avant et après SDK23, les versions Activity et Context de onAttach ont été appelées. Si vous pouvez trouver un scénario où ce n'est pas le cas, je vous suggère de créer un exemple de projet illustrant le problème et signalez-le à l'équipe Android .

Mise à jour 2: Je n'utilise que les fragments de la bibliothèque de support Android, car les bogues y sont corrigés plus rapidement. Il semble que le problème ci-dessus, où les substitutions ne sont pas appelées correctement, n'apparaît que si vous utilisez les fragments de structure.

320
Kuffs

Ceci est un autre grand changement de Google ... La modification suggérée: remplacer onAttach(Activity activity) par onAttach(Context context) a bloqué mes applications sur des API plus anciennes, car onAttach(Context context) ne sera pas appelé sur des fragments natifs.

J'utilise les fragments natifs (Android.app.Fragment). Je devais donc procéder comme suit pour que cela fonctionne à nouveau sur les anciennes API (<23).

Voici ce que j'ai fait:

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    // Code here
}

@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        // Code here
    }
}
43
Yoann Hercouet

Si vous utilisez les fragments de structure et que la version SDK du périphérique est inférieure à 23, OnAttach(Context context) ne sera pas appelé.

J'utilise plutôt des fragments de support, donc la dépréciation est corrigée et onAttach(Context context) est toujours appelé.

38
kikermo

Actuellement à partir du code de fragment onAttach, il n'est pas clair si Context est l'activité en cours: code source

public void onAttach(Context context) {
    mCalled = true;
    final Activity hostActivity = mHost == null ? null : mHost.getActivity();
    if (hostActivity != null) {
        mCalled = false;
        onAttach(hostActivity);
    }
}

Si vous allez jeter un oeil à getActivity, vous verrez le même appel

/**
 * Return the Activity this fragment is currently associated with.
 */
final public Activity getActivity() {
    return mHost == null ? null : mHost.getActivity();
}

Donc, si vous voulez être sûr que vous obtenez l'activité, utilisez getActivity() (dans onAttach dans votre Fragment) mais n'oubliez pas de vérifier null car si mHost est null votre activité sera null

10
royB
@Override
public void onAttach(Context context) {
    super.onAttach(context);

    Activity activity = context instanceof Activity ? (Activity) context : null;
}
6
worked

Bien qu'il semble que dans la plupart des cas, il suffit d'avoir onAttach(Context), il existe certains téléphones (c'est-à-dire: Xiaomi Redme Note 2) où il n'est pas appelé, ce qui provoque des exceptions NullPointerExceptions. Donc, pour être sûr, je suggère de laisser également la méthode obsolète:

// onAttach(Activity) is necessary in some Xiaomi phones
@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    _onAttach(activity);
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    _onAttach(context);
}

private void _onAttach(Context context) {
    // do your real stuff here
}
3
Gavriel

Téléchargez la dernière bibliothèque de support avec le gestionnaire de sdk et incluez

compile 'com.Android.support:appcompat-v7:23.1.1'

dans gradle.app et réglez la version de compilation sur api 23

3
Essah

vous utilisez probablement Android.support.v4.app.Fragment. Pour cela, au lieu de la méthode onAttach, utilisez simplement getActivity() pour obtenir le FragmentActivity auquel le fragment est associé. Sinon, vous pouvez utiliser la méthode onAttach(Context context).

1
LeoCoder

La réponse ci-dessous est liée à cet avertissement de dépréciation se produisant dans le didacticiel Fragments du site Web du développeur Android et peut ne pas être liée aux publications ci-dessus.

J'ai utilisé ce code dans la leçon de didacticiel et cela a fonctionné.

public void onAttach(Context context){
    super.onAttach(context);

    Activity activity = getActivity();

J'avais peur que cette activité soit nulle comme le stipule la documentation.

getActivity

FragmentActivity getActivity () Renvoie le FragmentActivity auquel ce fragment est actuellement associé. Peut renvoyer null si le fragment est associé à un contexte.

Mais onCreate sur la main_activity montre clairement que le fragment a été chargé et donc après cette méthode, l'appel de get activité à partir du fragment renverra la classe main_activity.

getSupportFragmentManager (). beginTransaction () .add (R.id.fragment_container, firstFragment) .commit ();

J'espère que je suis correct avec cela. Je suis un débutant absolu.

1
Roy Selim