Używanie kontekstu we fragmencie


664

Jak mogę uzyskać kontekst we fragmencie?

Muszę używać mojej bazy danych, której konstruktor przyjmuje w kontekście, ale getApplicationContext()i FragmentClass.thisnie działają więc co mogę zrobić?

Konstruktor bazy danych

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

Odpowiedzi:


1313

Możesz użyć getActivity(), który zwraca aktywność związaną z fragment.
Aktywność jest context (ponieważ Activityrozszerza się Context) .


212
getActivity () może zwrócić null, jeśli zostanie wywołane przed onAttach odpowiedniego fragmentu.
arne.jans

4
Czytałem tego bloga Google na temat wycieków pamięci ... android-developers.blogspot.com/2009/01/… . Jeśli użyję metody getActivity (), czy aplikacja nie będzie narażona na ryzyko wycieków pamięci? Blog sugeruje „Spróbuj użyć aplikacji kontekstowej zamiast działania kontekstowego”, co nie jest tak naprawdę możliwe, ponieważ getApplicationContext () działa tylko dla klasy Activity, a nie dla klasy Fragment.
Simon

40
Rozwiązaniem problemu odłączonych fragmentów jest przechowywanie wartości getActivity().getApplicationContext()zmiennej instancji podczas tworzenia fragmentu, a następnie używanie tego kontekstu, kiedy tylko chcesz wewnątrz klasy fragmentu. Ten kontekst przetrwa oderwanie fragmentów.
Piovezan,

8
Zamiast ominąć kontekst aplikacji, utwórz kontekst statyczny w klasie aplikacji i zainicjuj go onCreate (): MyApplication.sContext = getApplicationContext (); wtedy możesz uzyskać do niego dostęp z dowolnej aktywności / fragmentu, nie martwiąc się o oderwanie.
Eduko

3
@milaniez: getActivityzawsze był dostępny. Został getContexton dodany w API 23.
mhsmith

130

Aby wykonać powyższą odpowiedź, możesz zastąpić onAttachmetodę fragmentu:

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

3
Poleciłbym to, ponieważ getActivity () zwraca null, jeśli onAttach nie jest jeszcze wywoływany.
arne.jans

9
Pamiętaj jednak, że po wywołaniu funkcji onAttach () nie ma żadnych widoków. Więc nic nie możesz zrobić z widokami!
Zordid

2
@iambox co w razie DatabaseHelperpotrzeby FragmentActivityzamiast zamiast Activity? Na przykład dla Adapter...
Jago

4
Jeśli przechowujesz odniesienie do swojej działalności onAttach(Activity activity), powinieneś je opublikowaćonDetach()
vovahost

3
onAttachMetoda została zaniechana,Overrides deprecated method in 'android.support.v4.app.Fragment'
Muhammad Saqib

24

Zawsze używaj metody getActivity () , aby uzyskać kontekst dołączonej aktywności, ale zawsze pamiętaj o jednej rzeczy: fragmenty są nieco niestabilne i getActivityczasami zwracają wartość null, dlatego zawsze sprawdzaj metodę isAdded () fragmentu przed uzyskaniem kontekstu getActivity().


15
Nie powiedziałbym, że fragmenty są „nieco niestabilne”, wydaje się normalne, że getActivity () zwraca wartość null, gdy fragment nie należy do działania. Zakłada się, że getActivity () „nie powinien zwracać null” (co jest niepoprawne), co spowodowałoby niestabilność twojej aplikacji (a nie klasy Fragment).
personne3000

3
@ personne3000 Chciałbym usłyszeć więcej. Kiedy fragment nie należy do działania? Kiedy to się dzieje i dlaczego? Czy powinniśmy sprawdzać isAdded () we fragmencie, aby użyć getActivity ()? Jakaś zasada?
Sotti

2
@Sotti Zachęcam do utworzenia nowego pytania (lub poszukaj już istniejącego), ponieważ ten konkretny temat nieco różni się od pierwotnego pytania. Ogólne informacje znajdziesz na developer.android.com/guide/components/fragments.html#Lifecycle . Zasadniczo, przed onAttach i po onDetach, brak aktywności. Pomiędzy onAttach i onActivityCreated aktywność onCreate nie została jeszcze wywołana. Korzystając z getActivity (), upewnij się, że twoja aktywność została już utworzona i pomyśl, co by się stało, gdyby została zniszczona lub twój fragment został odłączony.
personne3000

22

Najłatwiejszym i najdokładniejszym sposobem uzyskania kontekstu fragmentu, który znalazłem, jest pobranie go bezpośrednio z metody ViewGroupwywołania onCreateView, przynajmniej tutaj, na pewno nie otrzymasz wartości null dla getActivity():

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

10
taki jest kontekst kontenera, myślę ... nie „ten kontekst”.
Fattie

2
@ AG1, czy mógłbyś wyjaśnić, dlaczego spowodował awarię kodu? To jak dotąd najlepsze rozwiązanie, jakie mam
Machado

3
W rzeczywistości w oknie dialogowym Fragmenty kontener może być pusty. Bądź ostrożny!
Lucas Teske,

Tego rozwiązania należy używać w trybie onViewCreated, a nie onCreateView.
Andrea De Simone

13

Wcześniej Używam onAttach (Activity activity)dostać contextwFragment

Problem

onAttach (Activity activity)Metoda została zaniechana poziomu API 23.

Rozwiązanie

Teraz, aby uzyskać kontekst Fragment, możemy użyćonAttach (Context context)

onAttach (Context context)

  • Wywoływany, gdy fragment jest dołączany po raz pierwszy context. onCreate(Bundle)zostanie wezwany po tym.

Dokumentacja

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

PRZYKŁADOWY KOD

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

}

UWAGA

Możemy również użyć getActivity(), aby uzyskać contextw Fragments ale getActivity()może wrócić null, jeśli Twój fragmentnie jest obecnie przypisane do rodzica activity,


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

6

Można również uzyskać kontekst z inflaterparametru podczas nadpisywania onCreateView.

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

5

Innym alternatywnym podejściem jest:

Możesz uzyskać kontekst, używając:

getActivity().getApplicationContext();

5

uzyskanie kontekstu wewnątrz Fragmentu będzie możliwe przy użyciu getActivity():

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • Uważaj, aby uzyskać Activityskojarzenie z fragmentem getActivity(), możesz go użyć, ale nie jest to zalecane, ponieważ spowoduje wyciek pamięci.

Myślę, że lepiej aproach musi być uzyskiwanie Activityz onAttach()metodą:

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

Nie powinieneś używać getActivity we fragmencie, aby uzyskać widok, chyba że ten widok i tak jest częścią działania. Dlaczego miałbyś zawyżać widok we fragmencie, a nawet nie odwoływać się do niczego?
tyczj

Ta odpowiedź dotyczy czegoś innego, mówisz o tym, w jakiej hierarchii widoków szukać widoków. Activity.findViewByIdJest to tylko wygodna metoda wyszukiwania widoku w widoku zarejestrowanej treści tego działania (ustawionym setContentView). W twoim poprawnym przykładzie wywołujesz View.findViewById, a nie wywołujesz Activity.findViewByIdmetodę w poprawnym widoku głównym. Zupełnie inny problem i oczywiście nie będziesz w stanie znaleźć swojego widoku w hierarchii widoków, która nie zawiera tego widoku.
JHH

3

getContext() wszedł w API 23. Zamień go na getActivity () wszędzie w kodzie.

Sprawdź, czy to naprawia błąd. Spróbuj użyć metod między docelowym a minimalnym poziomem API, w przeciwnym razie ten błąd się pojawi.


3

Od poziomu API 23 istnieje, getContext()ale jeśli chcesz obsługiwać starsze wersje, możesz ich używać, getActivity().getApplicationContext()a ja nadal zalecam korzystanie z wersji wsparcia, Fragmentktórą jest android.support.v4.app.Fragment.


2

getActivity() jest dzieckiem Kontekstu, więc powinno działać dla Ciebie


2

Użyj fragmentów z Biblioteki pomocy technicznej -

android.support.v4.app.Fragment

a następnie zastąpić

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

W ten sposób możesz mieć pewność, że kontekst zawsze będzie wartością inną niż null.


2

Masz różne opcje:

  • Jeśli twój minSDK <= 21, możesz użyć getActivity(), ponieważ jest to Context.
  • Jeśli twój minSDK wynosi> = 23, możesz użyć getContext().

Jeśli nie potrzebujesz obsługiwać starych wersji, skorzystaj z getContext().


2

W przypadku Kotlin możesz używać contextbezpośrednio we fragmentach. Ale w niektórych przypadkach znajdziesz błąd taki jak

Niezgodność typu: wnioskowany typ to Kontekst? ale kontekst był oczekiwany

do tego możesz to zrobić

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

Dzięki za skorzystanie z wersji Kotlin, która działa dobrze, ale staram się uzyskać Context dla Picasso.get (), z nim i to nigdy nie działa, próbowałem również wszystkiego, co mogłem z powyższych próbek, aby uzyskać kontekst. W najlepszym razie dostaję ten komunikat - Przekazano zbyt wiele argumentów ... Proszę o pomoc. val ctx = kontekst?: zwraca Picasso.get (ctx) .load (selectedGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage)
Ade

@ Ade W swoim fragmencie spróbuj użyć słowa „aktywność !!” zamiast „ctx” i daj mi znać, że to pomaga czy nie
Kishan Solanki

@ KishanSolanki124. Bardzo dziękuję za szybką odpowiedź. Wypróbowałem twoją sugestię, z tym samym rezultatem - Nie działa nadal. Dokładny komunikat o błędzie brzmi: - Zbyt wiele argumentów za publiczną otwartą zabawą get (): Picasso !. Ta wiadomość każe mi myśleć, może coś innego jest błędem ?. Cieszę się jednak, że znalazłem sposób na kontynuowanie mojej pracy za pomocą Picassa bez uzyskania kontekstu. Dzięki jeszcze raz.
Ade


2

Z API 29+ na Kotlinie musiałem to zrobić

activity?.applicationContext!!

Przykładem może być

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

Kontekst! = ApplicationContext
Gabriele Mariotti

1

W idealnym przypadku nie trzeba używać globałów. Fragment ma różne powiadomienia, z których jedno jest naActivityCreated. Możesz pobrać instancję działania w tym zdarzeniu cyklu życia fragmentu.

Następnie: możesz wyrejestrować fragment, aby uzyskać aktywność, kontekst lub kontekst aplikacji, jak chcesz:

this.getActivity()da ci uchwyt do działania this.getContext()da ci uchwyt do kontekstu this.getActivity().getApplicationContext()da ci uchwyt do kontekstu aplikacji. Zalecane jest używanie kontekstu aplikacji podczas przekazywania go do bazy danych.


1

Prostym sposobem jest użycie getActivity(). Ale myślę, że głównym nieporozumieniem związanym z użyciem getActivity()metody do uzyskania kontekstu jest wyjątek wskaźnika zerowego.

W tym celu najpierw sprawdź za pomocą isAdded()metody, która określi, czy jest dodana, czy nie, a następnie możemy użyć getActivity()do uzyskania kontekstu działania.


1
Czym różni się to od odpowiedzi Ankura Chaudhary'ego ?
Peter Mortensen

1

Możesz zadzwonić getActivity()lub

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

1

Możesz użyć metody getActivity (), aby uzyskać kontekst, lub możesz użyć metody getContext ().

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

Mam nadzieję, że to pomoże!


1
Istnieją inne odpowiedzi, które dostarczają pytania OP, i zostały opublikowane jakiś czas temu. Publikując odpowiedź zobacz: Jak napisać dobrą odpowiedź? , upewnij się, że dodajesz nowe rozwiązanie lub znacznie lepsze wyjaśnienie, szczególnie w przypadku odpowiedzi na starsze pytania.
help-info.de


0

Myślę, że możesz użyć

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

Możesz także użyć:

inflater.getContext();

ale wolałbym użyć

getActivity()

lub

getContext

0

Potrzebuję kontekstu do używania fragmentu arrayAdapter IN, kiedy korzystałem z getActivity, pojawia się błąd, ale kiedy zamieniam go na getContext , działa dla mnie

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

0

Możesz użyć getActivity()lub getContextwe fragmencie.

Dokumentacja

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

i

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

Pro wskazówka

Zawsze sprawdzaj, if(getActivity!=null)ponieważ może mieć wartość NULL, gdy fragment nie jest dołączony do działania. Czasami wykonanie długiej operacji w fragmencie (np. Pobieranie danych z pozostałych API) zajmuje trochę czasu. a jeśli użytkownik przejdzie do innego fragmentu. Wtedy getActivity będzie zerowy. I dostaniesz NPE, jeśli nie poradzisz sobie z tym.


To jest dokumentacja metody getActivity (), tylko po to, aby pokazać, że mogą one być zerowe. Tutaj mHost jest instancją FragmentHostCallbackklasy.
Khemraj

0

Na tobie fragment

((Name_of_your_Activity) getActivity()).helper

Aktywność

DbHelper helper = new DbHelper(this);

0

Fragment wewnątrz próbki kotlina pomógłby komuś

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

jeśli korzystasz z wiązania danych;

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

W przypadku inicjalizacji powiązania w onCreateView w ten sposób

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.