349 votes

Appeler une méthode d'activité à partir d'un fragment

J'essaie d'appeler une méthode dans mon activité à partir d'un fragment. Je veux que le fragment donne des données à la méthode et récupère les données lorsque la méthode revient. Je veux obtenir un résultat similaire à l'appel d'une méthode statique, mais sans l'utilisation de la méthode statique car elle crée des problèmes dans l'activité.

Nouveau pour les fragments, j'ai donc besoin d'une explication facile et pédagogique !

Merci !

892voto

Richard Points 2685

Du fragment à l'activité :

((YourActivityClassName)getActivity()).yourPublicMethod();

De l'activité au fragment :

FragmentManager fm = getSupportFragmentManager();

//if you added fragment via layout xml
YourFragmentClass fragment = (YourFragmentClass)fm.findFragmentById(R.id.your_fragment_id);
fragment.yourPublicMethod();

Si vous avez ajouté un fragment via le code et utilisé un tag lorsque vous avez ajouté votre fragment, utilisez findFragmentByTag à la place :

YourFragmentClass fragment = (YourFragmentClass)fm.findFragmentByTag("yourTag");

8 votes

Faites attention car des choses inattendues se produisent si le casting ne fonctionne pas :S

53 votes

Pour éviter le problème du moulage, utilisez : Activity act = getActivity() ; if (act instanceof YourActivityClassName) ((YourActivityClassName) act).yourPublicMethod() ; }

0 votes

@Richard : Comment pouvons-nous effectuer l'action inverse, par exemple, si nous devons exécuter la méthode d'un fragment à l'intérieur de l'activité ?

214voto

Marco Points 2932

Vous devriez probablement essayer de découpler le fragment de l'activité au cas où vous voudriez l'utiliser ailleurs. Vous pouvez le faire en créant une interface que votre activité implémente.

Vous devez donc définir une interface comme suit :

Supposons par exemple que vous vouliez donner à l'activité un String et qu'elle renvoie un Integer :

public interface MyStringListener{
    public Integer computeSomething(String myString);
}

Cela peut être défini dans le fragment ou dans un fichier séparé.

Ensuite, votre activité doit mettre en œuvre l'interface.

public class MyActivity extends FragmentActivity implements MyStringListener{

  @Override
  public Integer computeSomething(String myString){
   /** Do something with the string and return your Integer instead of 0 **/ 
   return 0;
  }

}

Ensuite, dans votre fragment, vous aurez une variable MyStringListener et vous définirez l'écouteur dans la méthode fragment onAttach(Activity activity).

public class MyFragment {

        private MyStringListener listener;

        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            try {
                listener = (MyStringListener) context;
            } catch (ClassCastException castException) {
                /** The activity does not implement the listener. */
            }
        }

    }

edit(17.12.2015) : onAttach(Activity activity) is deprecated, use onAttach(Context context) instead, it works as intended

La première réponse fonctionne certainement, mais elle couple votre fragment actuel avec l'activité de l'hôte. C'est une bonne pratique de garder le fragment découplé de l'activité hôte au cas où vous voudriez l'utiliser dans une autre activité.

63 votes

Pour tous ceux qui se penchent sur la question, bien que la réponse acceptée fonctionne évidemment, cette approche est meilleure et plus sûre du point de vue de la conception.

9 votes

Cette réponse est bien meilleure en termes de conception du code. de plus, elle ne provoquerait pas de plantage si l'activité est mal casted.

3 votes

+1 mais je n'utiliserais pas un try-catch dans le onAttach. Laissez-le échouer. Si l'écouteur est facultatif (c'est-à-dire que l'échec n'est pas approprié), ajoutez une méthode set/addListener au fragment.

79voto

Wasim K. Memon Points 3254

Pour Kotlin développeurs

(activity as YourActivityClassName).methodName()

Pour Java développeurs

((YourActivityClassName) getActivity()).methodName();

0 votes

Il donne une erreur dans kotlin si nous exécutons ce code y a-t-il un autre moyen ?

1 votes

Quand je l'exécute. J'obtiens une valeur nulle de ActivityClass, je pense que ce n'est pas la bonne façon de faire cela dans Kotlin, même sans erreur. ou peut-être un bug ?

0 votes

@JakeGarbo C'est la bonne façon de faire, sinon 12 personnes n'auraient pas voté pour. Deuxième chose un jour getActivity() Les retours sont nuls. Vérifiez ces questions sur la SO.

15voto

sivi Points 501

Mise à jour après avoir mieux compris le fonctionnement des fragments. Chaque fragment appartient à une activité parente. Il suffit donc d'utiliser :

getActivity().whatever

De l'intérieur du fragment. C'est une meilleure réponse car vous évitez les casts superflus. Si vous ne pouvez pas éviter les plâtres avec cette solution, utilisez celle qui suit.

\============

ce que tu dois faire c'est de lancer l'activité extérieure

((MainActivity) getActivity()).Method();

La création d'une nouvelle instance perturbera le cadre Android qui ne sera pas en mesure de la reconnaître. voir aussi :

https://stackoverflow.com/a/12014834/1984636

https://stackoverflow.com/a/2042829/1984636

9voto

A.Alqadomi Points 767

Bien que j'apprécie totalement la réponse de Marco, je pense qu'il est juste de souligner que vous pouvez également utiliser un cadre basé sur la publication et l'abonnement pour obtenir le même résultat. Par exemple, si vous optez pour le bus d'événements, vous pouvez procéder comme suit

fragment :

EventBus.getDefault().post(new DoSomeActionEvent()); 

Activité :

 @Subscribe
onSomeActionEventRecieved(DoSomeActionEvent doSomeActionEvent){
//Do something

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X