Utilisation du contexte dans un fragment


664

Comment puis-je obtenir le contexte dans un fragment?

Je dois utiliser ma base de données dont le constructeur prend dans le contexte, mais getApplicationContext()et FragmentClass.thisne travaille pas ce que je peux faire?

Constructeur de base de données

public Database(Context ctx)
{
    this.context = ctx;
    DBHelper = new DatabaseHelper(context);
}

Réponses:


1314

Vous pouvez utiliser getActivity(), qui renvoie l'activité associée à un fragment.
L'activité est un context (depuis Activitys'étend Context) .


212
getActivity () peut retourner null si elle est appelée avant onAttach du fragment respectif.
arne.jans

4
Je lisais ce blog Google sur les fuites de mémoire ... android-developers.blogspot.com/2009/01/… . Si j'utilise la méthode getActivity (), l'application ne risque-t-elle pas de fuir la mémoire? Le blog suggère "Essayez d'utiliser l'application contextuelle au lieu d'une activité contextuelle", ce qui n'est pas vraiment possible car getApplicationContext () ne fonctionne que pour la classe Activity et non la classe Fragment.
Simon

40
Une solution au problème des fragments détachés consiste à stocker la valeur de getActivity().getApplicationContext()dans une variable d'instance lorsque le fragment est créé, puis à utiliser ce contexte chaque fois que vous le souhaitez à l'intérieur de la classe de fragments. Ce contexte survivra aux détachements de fragments.
Piovezan

8
Au lieu de contourner le contexte d'application, créez un contexte statique à l'intérieur de votre classe Application et initialisez-le onCreate (): MyApplication.sContext = getApplicationContext (); alors vous pouvez y accéder à partir de n'importe quelle activité / fragment sans vous soucier du détachement.
Eduko

3
@milaniez: getActivitya toujours été disponible. C'est ce getContextqui a été ajouté dans l'API 23.
mhsmith

130

Pour faire comme la réponse ci-dessus, vous pouvez remplacer la onAttachméthode de fragment:

public static class DummySectionFragment extends Fragment{
...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        DBHelper = new DatabaseHelper(activity);
    }
}

3
Je recommanderais ceci, car getActivity () renvoie null si onAttach n'est pas encore appelé.
arne.jans

9
Mais gardez à l'esprit que lorsque onAttach () est appelé, il n'y a pas de vues. Donc, vous ne pouvez encore rien faire avec les vues!
Zordid

2
@iambox si DatabaseHelperbesoin d'un FragmentActivityau lieu d'un Activity? Par exemple, pour un Adapter...
Jago

4
Si vous stockez une référence à votre activité dans, onAttach(Activity activity)vous devez la publier dansonDetach()
vovahost

3
La onAttachméthode est obsolète,Overrides deprecated method in 'android.support.v4.app.Fragment'
Muhammad Saqib

24

Utilisez toujours la méthode getActivity () pour obtenir le contexte de votre activité attachée, mais souvenez-vous toujours d'une chose: les fragments sont légèrement instables et getActivityrenvoient parfois la valeur null, donc pour cela, vérifiez toujours la méthode de fragment isAdded () avant de récupérer le contexte par getActivity().


15
Je ne dirais pas que les fragments sont "légèrement instables", il semble tout à fait normal que getActivity () retourne null lorsque le fragment n'appartient pas à une activité. Cela suppose que getActivity () "ne devrait pas retourner null" (ce qui est faux) qui rendrait votre application (et non la classe Fragment) instable.
personne3000

3
@ personne3000 J'aimerais en savoir plus. Quand un fragment n'appartient-il pas à une activité? Quand cela se produit-il et pourquoi? Devrions-nous vérifier isAdded () dans le fragment afin d'utiliser getActivity ()? Une règle d'or?
Sotti

2
@Sotti Je vous encourage à créer une nouvelle question pour cela (ou à chercher une question existante), car ce sujet spécifique est un peu différent de la question d'origine. Vous pouvez jeter un œil à developer.android.com/guide/components/fragments.html#Lifecycle pour des informations générales. Fondamentalement, avant onAttach et après onDetach, aucune activité. Et entre onAttach et onActivityCreated, onCreate de l'activité n'a pas encore été appelé. Lorsque vous utilisez getActivity (), assurez-vous que votre activité a déjà été créée et pensez à ce qui se passerait si elle était détruite ou si votre fragment était détaché.
personne3000

22

Le moyen le plus simple et le plus précis pour obtenir le contexte du fragment que j'ai trouvé est de l'obtenir directement à partir de la méthode ViewGrouplorsque vous appelez onCreateViewau moins ici, vous êtes sûr de ne pas obtenir la valeur null pour getActivity():

public class Animal extends Fragment { 
  Context thiscontext;
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
  {
    thiscontext = container.getContext();

10
c'est le contexte du conteneur, je pense ... pas "ce contexte".
Fattie

2
@ AG1 pourriez-vous s'il vous plaît expliquer pourquoi il a planté votre code? C'est jusqu'à présent la meilleure solution que j'ai
Machado

3
En fait, sur dialogFragments, le conteneur peut être nul. Fais attention!
Lucas Teske

Cette solution doit être utilisée dans onViewCreated, pas onCreateView.
Andrea De Simone

13

Auparavant , j'utilise onAttach (Activity activity)pour obtenir contextenFragment

Problème

La onAttach (Activity activity)méthode est obsolète au niveau de l'API 23.

Solution

Maintenant, pour obtenir le contexte, Fragmentnous pouvons utiliseronAttach (Context context)

onAttach (Context context)

  • Appelé lorsqu'un fragment est attaché pour la première fois à son context. onCreate(Bundle)sera appelé après cela.

Documentation

/**
 * Called when a fragment is first attached to its context.
 * {@link #onCreate(Bundle)} will be called after this.
 */
@CallSuper
public void onAttach(Context context) {
    mCalled = true;
    final Activity hostActivity = mHost == null ? null : mHost.getActivity();
    if (hostActivity != null) {
        mCalled = false;
        onAttach(hostActivity);
    }
}

EXEMPLE DE CODE

public class FirstFragment extends Fragment {


    private Context mContext;
    public FirstFragment() {
        // Required empty public constructor
    }

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rooView=inflater.inflate(R.layout.fragment_first, container, false);

        Toast.makeText(mContext, "THIS IS SAMPLE TOAST", Toast.LENGTH_SHORT).show();
        // Inflate the layout for this fragment
        return rooView;
    }

}

REMARQUE

Nous pouvons également utiliser getActivity()pour obtenir contextdans Fragments mais getActivity()peut revenir nullsi le votre fragmentest pas à un parent activity,


11
@Override
public void onAttach(Activity activity) {
    // TODO Auto-generated method stub
    super.onAttach(activity);
    context=activity;
}

6

Vous pouvez également obtenir le contexte du inflaterparamètre lors de la substitution onCreateView.

public static class MyFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
        /* ... */
        Context context = inflater.getContext();
        /* ... */
    }
}

5

Une autre approche alternative est:

Vous pouvez obtenir le contexte en utilisant:

getActivity().getApplicationContext();

5

pour obtenir le contexte à l'intérieur du Fragment sera possible en utilisant getActivity():

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • Attention, pour obtenir les Activityassociés au fragment à l'aide getActivity(), vous pouvez l'utiliser mais il n'est pas recommandé de provoquer des fuites de mémoire.

Je pense qu'une meilleure approche doit être d'obtenir Activityla onAttach()méthode:

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

Vous ne devez pas utiliser getActivity dans un fragment pour obtenir une vue, à moins que cette vue ne fasse de toute façon partie de l'activité. Pourquoi voudriez-vous gonfler une vue dans un fragment sans même y référencer quoi que ce soit?
tyczj

Cette réponse est quelque chose de différent, vous parlez de quelle vue hiearchy pour rechercher des vues dans. Activity.findViewByIdEst juste une méthode pratique pour rechercher une vue en vue de contenu enregistré de cette activité (ensemble à travers setContentView). Dans votre exemple correct, vous appelez View.findViewByIdnon Activity.findViewById, et vous appelez la méthode sur la vue racine correcte . Problème totalement différent, et vous ne pourrez évidemment pas trouver votre vue dans une recherche de vue qui ne contient pas cette vue.
JHH

3

getContext() est venu dans l'API 23. Remplacez-le par getActivity () partout dans le code.

Voyez si cela corrige l'erreur. Essayez d'utiliser des méthodes qui se situent entre le niveau cible et le niveau API minimum, sinon cette erreur se produira.


3

Depuis le niveau 23 de l'API, il existe, getContext()mais si vous souhaitez prendre en charge les anciennes versions, vous pouvez utiliser getActivity().getApplicationContext()alors que je recommande toujours d'utiliser la version de support Fragmentqui est android.support.v4.app.Fragment.


2

getActivity() est un enfant de Context donc cela devrait fonctionner pour vous


2

Utiliser des fragments de la bibliothèque d'assistance -

android.support.v4.app.Fragment

puis remplacer

void onAttach (Context context) {
  this.context = context;
}

De cette façon, vous pouvez être sûr que le contexte sera toujours une valeur non nulle.


2

Vous avez différentes options:

  • Si votre minSDK <= 21, alors vous pouvez utiliser getActivity(), car il s'agit d'un Context.
  • Si votre minSDK est> = 23, alors vous pouvez utiliser getContext().

Si vous n'avez pas besoin de prendre en charge les anciennes versions, allez-y getContext().


2

Pour Kotlin, vous pouvez utiliser contextdirectement en fragments. Mais dans certains cas, vous trouverez une erreur comme

Non-concordance de type: le type déduit est Contexte? mais le contexte était attendu

pour cela, vous pouvez le faire

val ctx = context ?: return
textViewABC.setTextColor(ContextCompat.getColor(ctx, android.R.color.black))

Merci d'avoir utilisé une version de Kotlin, qui fonctionne bien, mais j'essaie d'obtenir Context pour Picasso.get (), avec elle et cela ne fonctionne jamais, j'ai également essayé tout ce que je peux à partir des exemples ci-dessus pour obtenir le contexte. Au mieux, je reçois ce message -Trop d'arguments passés ... S'il vous plaît aider. val ctx = context?: return Picasso.get (ctx) .load (selectedGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage)
Ade

@Ade Dans votre fragment, essayez d'utiliser "activité !!" au lieu de "ctx" et faites-moi savoir que cela aide ou non
Kishan Solanki

@ KishanSolanki124. Merci beaucoup pour la réponse rapide. J'ai essayé votre suggestion, avec le même résultat - Ne fonctionne toujours pas. L'invite d'erreur exacte est - Trop d'arguments pour le public open fun get (): Picasso !. Ce message me fait penser, peut-être que quelque chose d'autre est l'erreur?. Heureusement, j'ai trouvé un moyen de poursuivre mon travail en utilisant Picasso sans obtenir de contexte. Merci encore.
Ade

2

En kotlin, utilisez simplement activityau lieu degetActivity()


2

Avec API 29+ sur Kotlin, je devais faire

activity?.applicationContext!!

Un exemple serait

ContextCompat.getColor(activity?.applicationContext!!, R.color.colorAccent),

Context! = ApplicationContext
Gabriele Mariotti

1

Idéalement, vous ne devriez pas avoir besoin d'utiliser des globaux. Le fragment a différentes notifications, l'une d'elles étant onActivityCreated. Vous pouvez obtenir l'instance de l'activité dans cet événement de cycle de vie du fragment.

Ensuite: vous pouvez déréférencer le fragment pour obtenir l'activité, le contexte ou le contexte d'application comme vous le souhaitez:

this.getActivity()vous donnera le handle vers l'activité this.getContext()vous donnera un handle vers le contexte this.getActivity().getApplicationContext()vous donnera le handle vers le contexte de l'application. Vous devez de préférence utiliser le contexte de l'application lors de sa transmission à la base de données.


1

La manière la plus simple est d'utiliser getActivity(). Mais je pense que la confusion majeure de l'utilisation de la getActivity()méthode pour obtenir le contexte ici est une exception de pointeur nul.

Pour cela, vérifiez d'abord la isAdded()méthode qui déterminera si elle est ajoutée ou non, puis nous pouvons utiliser le getActivity()pour obtenir le contexte de l'activité.


1
En quoi est-ce différent de la réponse d' Ankur Chaudhary ?
Peter Mortensen

1

Vous pouvez appeler getActivity()ou,

public void onAttach(Context context) {
    super.onAttach(context);
    this.activity = (CashActivity) context;
    this.money = this.activity.money;
}

1

Vous pouvez utiliser la méthode getActivity () pour obtenir le contexte ou vous pouvez utiliser la méthode getContext ().

 View root = inflater.inflate(R.layout.fragment_slideshow, container, false);
    Context c = root.getContext();

J'espère que ça aide!


1
Il y a d'autres réponses qui fournissent la question du PO, et elles ont été publiées il y a quelque temps. Lors de la publication d'une réponse, voir: Comment puis-je écrire une bonne réponse? , assurez-vous d'ajouter une nouvelle solution ou une explication nettement meilleure, en particulier lorsque vous répondez à des questions plus anciennes.
help-info.de

0

La méthode getContext () permet d'utiliser le contexte de la classe dans une activité de fragment.


0

Je pense que vous pouvez utiliser

public static class MyFragment extends Fragment {
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

      Context context = getActivity.getContext();

  }
}

0
public class MenuFragment extends Fragment implements View.OnClickListener {
    private Context mContext;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        FragmentMenuBinding binding=FragmentMenuBinding.inflate(inflater,container,false);
        View view=binding.getRoot();
        mContext=view.getContext();
        return view;
    }
}

0

Vous pouvez également utiliser:

inflater.getContext();

mais je préfère utiliser

getActivity()

ou

getContext

0

J'ai besoin de contexte pour utiliser le fragment arrayAdapter IN, lorsque j'utilisais l' erreur getActivity , mais quand je le remplace par getContext, cela fonctionne pour moi

listView LV=getView().findViewById(R.id.listOFsensors);
LV.setAdapter(new ArrayAdapter<String>(getContext(),android.R.layout.simple_list_item_1 ,listSensorType));

0

Vous pouvez utiliser getActivity()ou getContexten Fragment.

Documentation

/**
 * Return the {@link FragmentActivity} this fragment is currently associated with.
 * May return {@code null} if the fragment is associated with a {@link Context}
 * instead.
 *
 * @see #requireActivity()
 */
@Nullable
final public FragmentActivity getActivity() {
    return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}

et

 /**
     * Return the {@link Context} this fragment is currently associated with.
     *
     * @see #requireContext()
     */
    @Nullable
    public Context getContext() {
        return mHost == null ? null : mHost.getContext();
    }

Conseil de pro

Vérifiez toujours if(getActivity!=null)car il peut être nul lorsque le fragment n'est pas attaché à l'activité. Parfois, une opération longue en fragment (comme la récupération de données à partir de l'api de repos) prend un certain temps. et si l'utilisateur accède à un autre fragment. Alors getActivity sera nul. Et vous obtiendrez NPE si vous ne l'avez pas géré.


Ceci est une documentation de la méthode getActivity (), juste pour montrer que ceux-ci peuvent être nuls. Ici mHost est une instance de FragmentHostCallbackclasse.
Khemraj

0

Sur toi fragment

((Name_of_your_Activity) getActivity()).helper

En activité

DbHelper helper = new DbHelper(this);

0

Un fragment intérieur pour un échantillon de kotlin aiderait quelqu'un

textViewStatus.setTextColor(ContextCompat.getColor(context!!, R.color.red))

si vous utilisez la liaison de données;

bindingView.textViewStatus.setTextColor(ContextCompat.getColor(context!!, R.color.red))

Où bindingView est initialisé dans onCreateView comme ceci

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

bindingView = DataBindingUtil.inflate(inflater, R.layout.your_layout_xml, container, false)

0

La méthode requireContext () est l'option la plus simple

requireContext()

Exemple

MyDatabase(requireContext())
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.