Utilizzo del contesto in un frammento


664

Come posso ottenere il contesto in un frammento?

Devo usare il mio database il cui costruttore accetta il contesto, ma getApplicationContext()e FragmentClass.thisnon funziona, quindi cosa posso fare?

Costruttore di database

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

Risposte:


1314

È possibile utilizzare getActivity(), che restituisce l'attività associata a fragment.
L'attività è un context (poiché si Activityestende Context) .


212
getActivity () può restituire null se viene chiamato prima su onAttach del rispettivo frammento.
arne.jans,

4
Stavo leggendo questo blog di Google su perdite di memoria ... android-developers.blogspot.com/2009/01/… . Se uso il metodo getActivity () l'app non sarebbe a rischio di perdite di memoria? Il blog suggerisce "Prova a utilizzare l'applicazione di contesto invece di un'attività di contesto" che non è realmente possibile in quanto getApplicationContext () funziona solo per la classe Activity e non per la classe Fragment.
Simon,

40
Una soluzione al problema dei frammenti staccati è quella di memorizzare il valore di getActivity().getApplicationContext()una variabile di istanza quando viene creato il frammento e quindi utilizzare quel contesto ogni volta che si desidera all'interno della classe di frammenti. Quel contesto sopravviverà ai distacchi di frammenti.
Piovezan,

8
Invece di passare per il contesto dell'applicazione, creare un contesto statico all'interno della classe Application e inizializzarlo onCreate (): MyApplication.sContext = getApplicationContext (); quindi puoi accedervi da qualsiasi attività / frammento senza preoccuparti del distacco.
Eduko,

3
@milaniez: getActivityè sempre stato disponibile. È getContextstato aggiunto in API 23.
mhsmith,

130

Per fare come la risposta sopra, è possibile ignorare il onAttachmetodo del frammento:

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

3
Lo consiglierei, poiché getActivity () restituisce null se onAttach non è ancora stato chiamato.
arne.jans,

9
Tuttavia, tieni presente che quando viene chiamato onAttach (), non ci sono viste. Quindi non puoi ancora fare nulla con le viste!
Zordid,

2
@iambox e se fosse DatabaseHelpernecessario un FragmentActivityinvece di un Activity? Ad esempio, per un Adapter...
Jago,

4
Se memorizzi un riferimento alla tua attività onAttach(Activity activity), dovresti rilasciarlo inonDetach()
vovahost il

3
Il onAttachmetodo è stato deprecato,Overrides deprecated method in 'android.support.v4.app.Fragment'
Muhammad Saqib

24

Usa sempre il metodo getActivity () per ottenere il contesto dell'attività associata, ma ricorda sempre una cosa: i frammenti sono leggermente instabili e getActivityrestituiscono null alcune volte, quindi, controlla sempre il metodo del frammento isAdded () prima di ottenere il contesto getActivity().


15
Non direi che i frammenti sono "leggermente instabili", sembra abbastanza normale che getActivity () restituisca null quando il frammento non appartiene a un'attività. Si presuppone che getActivity () "non debba restituire null" (che è errato) che renderebbe instabile la tua app (e non la classe Fragment).
personne3000,

3
@ personne3000 Mi piacerebbe saperne di più. Quando un frammento non appartiene a un'attività? Quando sta succedendo questo e perché? Dovremmo controllare isAdded () nel frammento per usare getActivity ()? Qualche regola empirica?
Sotti,

2
@Sotti Ti incoraggio a creare una nuova domanda per questo (o cercarne uno esistente), poiché questo argomento specifico è un po 'diverso dalla domanda originale. Puoi dare un'occhiata a developer.android.com/guide/components/fragments.html#Lifecycle per informazioni generali. Fondamentalmente, prima di onAttach e dopo onDetach, nessuna attività. E tra onAttach e onActivityCreated, onCreate dell'attività non è stato ancora chiamato. Quando usi getActivity (), assicurati che la tua attività sia già stata creata e pensa a cosa accadrebbe se fosse distrutto o il frammento fosse staccato.
personne3000,

22

Il modo più semplice e preciso per ottenere il contesto del frammento che ho trovato è quello di ottenerlo direttamente da ViewGroupquando chiami il onCreateViewmetodo almeno qui sei sicuro di non ottenere null per getActivity():

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

10
questo è il contesto del contenitore, penso ... non "questo contesto".
Fattie,

2
@ AG1 potresti spiegare perché ha provocato l'arresto anomalo del codice? Questa è finora la soluzione migliore che ho
Machado,

3
In realtà su dialogFragments il contenitore può essere nullo. Stai attento!
Lucas Teske,

Questa soluzione deve essere utilizzata in onViewCreated, non onCreateView.
Andrea De Simone,

13

In precedenza sto usando onAttach (Activity activity)per arrivare contextaFragment

Problema

Il onAttach (Activity activity)metodo è stato deprecato nel livello API 23.

Soluzione

Ora per ottenere il contesto Fragmentpossiamo usareonAttach (Context context)

onAttach (Context context)

  • Chiamato quando un frammento viene collegato per la prima volta al suo context. onCreate(Bundle)verrà chiamato dopo questo.

Documentazione

/**
 * 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);
    }
}

CODICE DI ESEMPIO

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;
    }

}

NOTA

Possiamo anche usare getActivity()per arrivare contextin Fragments , ma getActivity()può tornare nullse il vostro fragmentnon è attualmente collegato a un genitore activity,


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

6

È inoltre possibile ottenere il contesto dal inflaterparametro, durante l'override onCreateView.

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

5

Un altro approccio alternativo è:

Puoi ottenere il contesto usando:

getActivity().getApplicationContext();

5

per ottenere il contesto all'interno del frammento sarà possibile usando getActivity():

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • Fai attenzione, per ottenere il Activityassociato con il frammento usando getActivity(), puoi usarlo ma non è raccomandato che causerà perdite di memoria.

Penso che un approccio migliore debba essere ottenere Activitydal onAttach()metodo:

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

Non dovresti usare getActivity in un frammento per ottenere una vista a meno che quella vista non faccia comunque parte dell'attività. Perché dovresti gonfiare una vista in un frammento e non farne nemmeno riferimento?
tyczj,

Questa risposta riguarda qualcosa di diverso, stai parlando della vista in cui cercare le viste. Activity.findViewByIdÈ solo un metodo pratico per cercare una vista nella vista del contenuto registrato di quell'attività (impostata attraverso setContentView). Nel tuo esempio corretto stai chiamando View.findViewById, no Activity.findViewById, e stai invocando il metodo nella vista radice corretta . Problema totalmente diverso, e ovviamente non sarai in grado di trovare la tua vista in una vista che non ha quella vista.
JHH,

3

getContext() è arrivato in API 23. Sostituiscilo con getActivity () ovunque nel codice.

Vedi se corregge l'errore. Prova a utilizzare metodi che si trovano tra la destinazione e il livello minimo dell'API, altrimenti si verificherà questo errore.


3

Dal livello API 23 esiste, getContext()ma se si desidera supportare le versioni precedenti è possibile utilizzare getActivity().getApplicationContext()mentre io consiglio ancora di utilizzare la versione di supporto di Fragmentcui è android.support.v4.app.Fragment.


2

getActivity() è figlio del contesto, quindi dovrebbe funzionare per te


2

Usa frammenti dalla libreria di supporto -

android.support.v4.app.Fragment

e quindi sovrascrivere

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

In questo modo puoi essere sicuro che il contesto sarà sempre un valore non nullo.


2

Hai diverse opzioni:

  • Se il tuo minSDK <= 21, è possibile utilizzare getActivity(), poiché questo è un Context.
  • Se minSDK è> = 23, è possibile utilizzare getContext().

Se non è necessario supportare le versioni precedenti, procedere con getContext().


2

Per Kotlin puoi usare contextdirettamente nei frammenti. Ma in alcuni casi troverai un errore simile

Tipo non corrispondente: il tipo inferito è Context? ma il contesto era previsto

per questo puoi farlo

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

Grazie per avvalermi di una versione di Kotlin, che funziona bene, tuttavia sto cercando di ottenere Context per Picasso.get (), con esso e non funziona mai, ho provato tutto il possibile dagli esempi sopra e per ottenere il contesto. Nella migliore delle ipotesi ricevo questo messaggio -Troppo molti argomenti passati ... Per favore aiutatemi. val ctx = context?: return Picasso.get (ctx) .load (selectedGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage)
Ade,

@Ade Nel tuo frammento, prova a usare "attività !!" invece di "ctx" e fammi sapere che aiuta o no
Kishan Solanki,

@ KishanSolanki124. Grazie mille per la rapida risposta. Ho provato il tuo suggerimento, con lo stesso risultato - Non funziona ancora. Il messaggio di errore esatto è: troppi argomenti per public open fun get (): Picasso !. Questo messaggio mi fa pensare, forse qualcos'altro è l'errore ?. Volentieri, ho trovato il modo di andare avanti con il mio lavoro usando Picasso senza ottenere contesto. Grazie ancora.
Ade,


2

Con API 29+ su Kotlin, ho dovuto farlo

activity?.applicationContext!!

Un esempio sarebbe

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

Context! = ApplicationContext
Gabriele Mariotti,

1

Idealmente, non dovresti avere bisogno di usare i globi. Il frammento ha diverse notifiche, una delle quali è onActivityCreated. È possibile ottenere l'istanza dell'attività in questo evento del ciclo di vita del frammento.

Quindi: puoi dereferenziare il frammento per ottenere attività, contesto o contenuto dell'applicazione come desideri:

this.getActivity()ti darà l'handle per l'attività this.getContext()ti darà un handle per il contesto this.getActivity().getApplicationContext()ti darà l'handle per il contesto dell'applicazione. È preferibile utilizzare il contesto dell'applicazione quando lo si passa al db.


1

Il modo semplice è usare getActivity(). Ma penso che la maggiore confusione nell'uso del getActivity()metodo per ottenere il contesto qui sia un'eccezione puntatore null.

Per questo, controlla prima con il isAdded()metodo che determinerà se viene aggiunto o meno, quindi possiamo usare il getActivity()per ottenere il contesto dell'Attività.


1
In che modo differisce dalla risposta di Ankur Chaudhary ?
Peter Mortensen,

1

Puoi chiamare getActivity()o,

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

1

È possibile utilizzare il metodo getActivity () per ottenere il contesto oppure È possibile utilizzare il metodo getContext ().

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

Spero possa essere d'aiuto!


1
Esistono altre risposte che forniscono la domanda del PO e sono state pubblicate qualche tempo fa. Quando invio una risposta, vedi: Come posso scrivere una buona risposta? , assicurati di aggiungere una nuova soluzione o una spiegazione sostanzialmente migliore, soprattutto quando rispondi a domande precedenti.
help-info.de

0

Il metodo getContext () aiuta a usare il contesto della classe in un'attività frammentata.


0

Penso che tu possa usare

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

Inoltre puoi usare:

inflater.getContext();

ma preferirei usare

getActivity()

o

getContext

0

Ho bisogno del contesto per usare il frammento arrayAdapter IN, quando stavo usando l' errore getActivity ma quando lo sostituisco con getContext funziona per me

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

0

Puoi usare getActivity()o getContextin Frammento.

Documentazione

/**
 * 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();
}

e

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

Suggerimento professionale

Controlla sempre if(getActivity!=null)perché può essere nullo quando il frammento non è associato all'attività. A volte l'esecuzione di operazioni lunghe in frammenti (come il recupero di dati da API di resto) richiede del tempo. e se l'utente naviga verso un altro frammento. Quindi getActivity sarà null. E otterrai NPE se non lo gestissi.


Questa è una documentazione del metodo getActivity (), solo per dimostrare che questi possono essere nulli. Qui mHost è un'istanza di FragmentHostCallbackclasse.
Khemraj,

0

Sul tuo frammento

((Name_of_your_Activity) getActivity()).helper

In attività

DbHelper helper = new DbHelper(this);

0

Il frammento interno per il campione di kotlin aiuterebbe qualcuno

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

se usi la banca dati;

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

Dove bindingView è inizializzato in onCreateView in questo modo

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

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

0

Il metodo requireContext () è l'opzione più semplice

requireContext()

Esempio

MyDatabase(requireContext())
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.