Verwenden des Kontexts in einem Fragment


663

Wie kann ich den Kontext in einem Fragment erhalten?

Ich brauche meine Datenbank , deren Konstruktor nimmt im Kontext zu verwenden, aber getApplicationContext()und FragmentClass.thisfunktionieren nicht so , was kann ich tun?

Datenbankkonstruktor

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

Antworten:


1312

Sie können verwenden getActivity(), wodurch die mit a verknüpfte Aktivität zurückgegeben wird fragment.
Die Aktivität ist a context (da Activityerstreckt sich Context) .


212
getActivity () kann null zurückgeben, wenn es vor onAttach des jeweiligen Fragments aufgerufen wird.
Arne.jans

4
Ich habe diesen Google-Blog über Speicherlecks gelesen ... android-developers.blogspot.com/2009/01/… . Wenn ich die Methode getActivity () verwende, besteht für die App kein Risiko für Speicherverluste? Der Blog schlägt vor, "Verwenden Sie die Kontextanwendung anstelle einer Kontextaktivität", was nicht wirklich möglich ist, da getApplicationContext () nur für die Activity-Klasse und nicht für die Fragment-Klasse funktioniert.
Simon

40
Eine Lösung für das Problem der getrennten Fragmente besteht darin, den Wert von getActivity().getApplicationContext()in einer Instanzvariablen zu speichern , wenn das Fragment erstellt wird, und diesen Kontext dann zu verwenden, wann immer Sie möchten, innerhalb der Fragmentklasse. Dieser Kontext wird Fragmentablösungen überleben.
Piovezan

8
Anstatt den Anwendungskontext weiterzugeben, erstellen Sie einen statischen Kontext in Ihrer Anwendungsklasse und initialisieren Sie ihn onCreate (): MyApplication.sContext = getApplicationContext (); Dann können Sie von jeder Aktivität / jedem Fragment darauf zugreifen, ohne sich Gedanken über die Ablösung machen zu müssen.
Eduko

3
@milaniez: war getActivityschon immer verfügbar. Es ist das, getContextwas in API 23 hinzugefügt wurde.
mhsmith

130

Um die obige Antwort zu geben, können Sie die onAttachFragmentmethode überschreiben :

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

3
Ich würde dies empfehlen, da getActivity () null zurückgibt, wenn onAttach noch nicht aufgerufen wird.
Arne.jans

9
Beachten Sie jedoch, dass beim Aufruf von onAttach () keine Ansichten vorhanden sind. Mit Ansichten kann man also noch nichts anfangen!
Zordid

2
@iambox was ist wenn DatabaseHelpernötig ein FragmentActivitystatt eines Activity? Zum Beispiel für einen Adapter...
Jago

4
Wenn Sie einen Verweis auf Ihre Aktivität in speichern onAttach(Activity activity), sollten Sie ihn inonDetach()
vovahost

3
Die onAttachMethode ist veraltet,Overrides deprecated method in 'android.support.v4.app.Fragment'
Muhammad Saqib

24

Verwenden Sie immer die Methode getActivity () , um den Kontext Ihrer angehängten Aktivität abzurufen , aber denken Sie immer an eines: Fragmente sind leicht instabil undgetActivity manchmal null zurück. Überprüfen Sie daher immer die isAdded () -Methode des Fragments, bevor Sie den Kontext abrufengetActivity() .


15
Ich würde nicht sagen, dass Fragmente "leicht instabil" sind. Es scheint ganz normal, dass getActivity () null zurückgibt, wenn das Fragment nicht zu einer Aktivität gehört. Es wird davon ausgegangen, dass getActivity () "nicht null zurückgeben sollte" (was falsch ist), was Ihre App (und nicht die Fragment-Klasse) instabil machen würde.
personne3000

3
@ personne3000 Ich würde gerne mehr hören. Wann gehört ein Fragment nicht zu einer Aktivität? Wann passiert das und warum? Sollten wir isAdded () im Fragment überprüfen, um getActivity () zu verwenden? Eine Faustregel?
Sotti

2
@Sotti Ich ermutige Sie, eine neue Frage zu erstellen (oder nach einer vorhandenen zu suchen), da sich dieses spezielle Thema ein wenig von der ursprünglichen Frage unterscheidet. Allgemeine Informationen finden Sie unter developer.android.com/guide/components/fragments.html#Lifecycle . Grundsätzlich vor onAttach und nach onDetach keine Aktivität. Und zwischen onAttach und onActivityCreated wurde onCreate der Aktivität noch nicht aufgerufen. Stellen Sie bei der Verwendung von getActivity () sicher, dass Ihre Aktivität bereits erstellt wurde, und überlegen Sie, was passieren würde, wenn sie zerstört oder Ihr Fragment getrennt würde.
personne3000

22

Der einfachste und genaueste Weg, um den Kontext des gefundenen Fragments zu erhalten, besteht darin, es direkt von der Methode abzurufen, ViewGroupwenn Sie die onCreateViewMethode aufrufen. Zumindest hier erhalten Sie sicher keine Null für getActivity():

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

10
Das ist der Kontext des Containers, denke ich ... nicht "dieser Kontext".
Fattie

2
@ AG1 Könnten Sie bitte erklären, warum Ihr Code abgestürzt ist? Dies ist bisher die beste Lösung, die ich habe
Machado

3
Eigentlich auf dialogFragments der Behälter kann null sein. Sei vorsichtig!
Lucas Teske

Diese Lösung sollte in onViewCreated und nicht in onCreateView verwendet werden.
Andrea De Simone

13

Früher bin ich mit onAttach (Activity activity)bekommen contextinFragment

Problem

Die onAttach (Activity activity)Methode wurde in API-Level 23 nicht mehr unterstützt.

Lösung

Nun, um den Kontext zu erhalten Fragment, können wir verwendenonAttach (Context context)

onAttach (Context context)

  • Wird aufgerufen, wenn ein Fragment zum ersten Mal an sein angehängt wird context. onCreate(Bundle)wird danach aufgerufen.

Dokumentation

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

BEISPIELCODE

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

}

HINWEIS

Wir können auch verwenden getActivity(), um contexteinzusteigen Fragments , getActivity()können aber zurückkehren, nullwenn Ihr fragmentMitglied derzeit keinem Elternteil zugeordnet activityist.


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

6

Sie können den Kontext auch inflaterbeim Überschreiben aus dem Parameter abrufen onCreateView.

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

5

Ein anderer alternativer Ansatz ist:

Sie können den Kontext erhalten mit:

getActivity().getApplicationContext();

5

Um den Kontext innerhalb des Fragments zu erhalten, ist Folgendes möglich getActivity():

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • Seien Sie vorsichtig, um das Activitymit dem Fragment verknüpfte zu verwenden getActivity(). Sie können es verwenden, es wird jedoch nicht empfohlen, da es zu Speicherlecks führt.

Ich denke, ein besserer Ansatz muss darin bestehen, das Activityaus der onAttach()Methode herauszuholen :

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

Sie sollten getActivity nicht in einem Fragment verwenden, um eine Ansicht abzurufen, es sei denn, diese Ansicht ist ohnehin Teil der Aktivität. Warum würden Sie eine Ansicht in einem Fragment aufblasen und dann nicht einmal etwas davon referenzieren?
Tyczj

Bei dieser Antwort handelt es sich um etwas anderes. Sie sprechen über die Ansicht, in der nach Ansichten gesucht werden soll. Dies Activity.findViewByIdist nur eine bequeme Methode, um nach einer Ansicht in der registrierten Inhaltsansicht dieser Aktivität zu suchen (durchgesetzt setContentView). In Ihrem korrekten Beispiel rufen Sie View.findViewByIdnicht auf Activity.findViewByIdund rufen die Methode in der richtigen Stammansicht auf. Ganz anderes Problem, und offensichtlich können Sie Ihre Ansicht nicht in einer Ansicht finden, die diese Ansicht nicht enthält.
JHH

3

getContext() kam in API 23. Ersetzen Sie es überall im Code durch getActivity ().

Überprüfen Sie, ob der Fehler behoben ist. Versuchen Sie, Methoden zu verwenden, die zwischen der Ziel- und der Minimun-API-Ebene liegen. Andernfalls tritt dieser Fehler auf.


3

Seit API-Level 23 gibt es getContext()aber wenn Sie ältere Versionen unterstützen möchten, können Sie diese verwenden, getActivity().getApplicationContext()während ich weiterhin empfehle, die Support-Version Fragmentdavon zu verwenden android.support.v4.app.Fragment.


2

getActivity() ist ein Kind von Context, so dass für Sie arbeiten sollte


2

Verwenden Sie Fragmente aus der Support Library -

android.support.v4.app.Fragment

und dann überschreiben

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

Auf diese Weise können Sie sicher sein, dass der Kontext immer ein Wert ungleich Null ist.


2

Sie haben verschiedene Möglichkeiten:

  • Wenn Ihr minSDK <= 21 ist, können Sie verwenden getActivity(), da dies ein ist Context.
  • Wenn Ihr minSDK> = 23 ist, können Sie verwenden getContext().

Wenn Sie alte Versionen nicht unterstützen müssen, gehen Sie mit getContext().


2

Für Kotlin können Sie contextdirekt in Fragmenten verwenden. Aber in einigen Fällen finden Sie einen Fehler wie

Typinkongruenz: Der abgeleitete Typ ist Kontext? aber der Kontext wurde erwartet

dafür kannst du das machen

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

Vielen Dank, dass Sie eine Kotlin-Version verwendet haben, die gut funktioniert. Ich versuche jedoch, Context für Picasso.get () zu erhalten, und es funktioniert nie. Ich habe auch alles versucht, was ich kann, aus den obigen Beispielen, um den Kontext zu erhalten. Bestenfalls bekomme ich diese Nachricht - Zu viele Argumente wurden übergeben ... Bitte helfen Sie. val ctx = context ?: Picasso.get (ctx) .load (selectedGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage) zurückgeben
Ade

@Ade Versuchen Sie in Ihrem Fragment, "Aktivität !!" zu verwenden. anstelle von "ctx" und lassen Sie mich wissen, ob es hilft oder nicht
Kishan Solanki

@ KishanSolanki124. Vielen Dank für die schnelle Antwort. Ich habe Ihren Vorschlag mit dem gleichen Ergebnis ausprobiert - funktioniert immer noch nicht. Die genaue Fehleraufforderung lautet - Zu viele Argumente für öffentlichen Open Fun get (): Picasso!. Diese Nachricht lässt mich denken, vielleicht ist etwas anderes der Fehler?. Gerne habe ich mit Picasso einen Weg gefunden, mit meiner Arbeit fortzufahren, ohne Kontext zu bekommen. Danke noch einmal.
Ade

2

In Kotlin einfach activityanstelle von verwendengetActivity()


2

Mit API 29+ auf Kotlin musste ich tun

activity?.applicationContext!!

Ein Beispiel wäre

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

Kontext! = ApplicationContext
Gabriele Mariotti vor

1

Idealerweise sollten Sie keine Globals verwenden müssen. Das Fragment verfügt über verschiedene Benachrichtigungen, von denen eine onActivityCreated ist. Sie können die Instanz der Aktivität in diesem Lebenszyklusereignis des Fragments abrufen.

Dann: Sie können das Fragment dereferenzieren, um Aktivität, Kontext oder Anwendungskontext zu erhalten, wie Sie möchten:

this.getActivity()gibt Ihnen das Handle für die Aktivität this.getContext()gibt Ihnen ein Handle für den Kontext this.getActivity().getApplicationContext()gibt Ihnen das Handle für den Anwendungskontext. Sie sollten den Anwendungskontext vorzugsweise verwenden, wenn Sie ihn an die Datenbank weitergeben.


1

Der einfache Weg ist zu verwenden getActivity(). Aber ich denke die größte Verwirrung bei der Verwendung dergetActivity() Methode zum Abrufen des Kontexts hier eine Nullzeigerausnahme ist.

Überprüfen Sie dazu zunächst die isAdded()Methode , mit der ermittelt wird, ob sie hinzugefügt wurde oder nicht, und verwenden Sie dann die getActivity(), um den Kontext der Aktivität abzurufen.


1
Wie unterscheidet sich das von Ankur Chaudharys Antwort ?
Peter Mortensen

1

Sie können anrufen getActivity()oder,

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

1

Sie können die Methode getActivity () verwenden, um den Kontext abzurufen, oder Sie können die Methode getContext () verwenden.

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

Ich hoffe, es hilft!


1
Es gibt andere Antworten, die die Frage des OP stellen, und sie wurden vor einiger Zeit veröffentlicht. Wenn Sie eine Antwort veröffentlichen, lesen Sie: Wie schreibe ich eine gute Antwort? Bitte stellen Sie sicher, dass Sie entweder eine neue Lösung oder eine wesentlich bessere Erklärung hinzufügen, insbesondere wenn Sie ältere Fragen beantworten.
help-info.de

0

Die Methode getContext () hilft dabei, den Kontext der Klasse in einer Fragmentaktivität zu verwenden.


0

Ich denke du kannst es benutzen

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

Sie können auch verwenden:

inflater.getContext();

aber ich würde es vorziehen zu verwenden

getActivity()

oder

getContext

0

Ich benötige Kontext für die Verwendung des ArrayAdapter IN-Fragments. Wenn ich getActivity verwendet habe , tritt ein Fehler auf, aber wenn ich ihn durch getContext ersetze , funktioniert er für mich

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

0

Sie können getActivity()oder getContextin Fragment verwenden.

Dokumentation

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

und

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

Profi-Tipp

Überprüfen Sie immer, if(getActivity!=null)ob es null sein kann, wenn das Fragment nicht an die Aktivität angehängt ist. Manchmal dauert es einige Zeit, lange Operationen in Fragmenten durchzuführen (z. B. Daten von der Rest-API abzurufen). und wenn der Benutzer zu einem anderen Fragment navigiert. Dann ist getActivity null. Und Sie erhalten NPE, wenn Sie nicht damit umgehen.


Dies ist eine Dokumentation der Methode getActivity (), um zu zeigen, dass diese null sein können. Hier ist mHost eine Instanz der FragmentHostCallbackKlasse.
Khemraj

0

Auf dich Fragment

((Name_of_your_Activity) getActivity()).helper

Über Aktivität

DbHelper helper = new DbHelper(this);

0

Innenfragment für Kotlin-Probe würde jemandem helfen

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

wenn Sie Datenbindung verwenden;

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

Wo BindingView in onCreateView wie folgt initialisiert wird

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

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

0

Die Methode requireContext () ist die einfachste Option

requireContext()

Beispiel

MyDatabase(requireContext())
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.