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);
}
tyczj
quelle

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) .

Nilesh Rathod
quelle
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);
    }
}
iambox
quelle
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() .

Ankur Chaudhary
quelle
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();
Amerdroid
quelle
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.

Nilesh Rathod
quelle
11
@Override
public void onAttach(Activity activity) {
    // TODO Auto-generated method stub
    super.onAttach(activity);
    context=activity;
}
Taran Mahal
quelle
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();
        /* ... */
    }
}
luizfls
quelle
5

Ein anderer alternativer Ansatz ist:

Sie können den Kontext erhalten mit:

getActivity().getApplicationContext();
Codercat
quelle
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;
}
Jorgesys
quelle
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.

Naveen
quelle
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.

Androbin
quelle
2

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

Qazimusab
quelle
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.

Lomza
quelle
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().

Jorge
quelle
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))
Kishan Solanki
quelle
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()

Abduhafiz
quelle
2

Mit API 29+ auf Kotlin musste ich tun

activity?.applicationContext!!

Ein Beispiel wäre

ContextCompat.getColor(activity?.applicationContext!!, R.color.colorAccent),
Alles ist gut
quelle
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.

user5610809
quelle
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.

Saubhagya Ranjan Das
quelle
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;
}
蔡健烽
quelle
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!

Rishabh Sharma
quelle
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.

Gavine Joyce
quelle
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();

  }
}
aswinbhim nath
quelle
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;
    }
}
Mohsinali
quelle
0

Sie können auch verwenden:

inflater.getContext();

aber ich würde es vorziehen zu verwenden

getActivity()

oder

getContext
Entdecker
quelle
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));
ghazaleh javaheri
quelle
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.

Khemraj
quelle
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);
Kinggeov
quelle
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)
Shihab Uddin
quelle
0

Die Methode requireContext () ist die einfachste Option

requireContext()

Beispiel

MyDatabase(requireContext())
JoséAntonio Campillo
quelle