Використання контексту у фрагменті


664

Як я можу отримати фрагмент у фрагменті?

Мені потрібно використовувати свою базу даних, конструктор якого приймає в контексті, але getApplicationContext()і FragmentClass.thisне працює так , що я можу зробити?

Конструктор баз даних

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

Відповіді:


1313

Ви можете використовувати getActivity(), що повертає активність, пов'язану з a fragment.
Діяльність context (з моменту Activityпродовження Context) .


212
getActivity () може повернути нуль, якщо він буде викликаний перед onAttach відповідного фрагмента.
arne.jans

4
Я читав цей блог Google про витоки пам’яті ... android-developers.blogspot.com/2009/01/… . Якщо я використовую метод getActivity (), додаток не загрожує витоком пам'яті? Блог пропонує "Спробуйте використовувати контекстну програму замість контекстної діяльності", що насправді неможливо, оскільки getApplicationContext () працює лише для класу Activity, а не для класу Fragment.
Саймон

40
Рішення проблеми відокремлених фрагментів полягає в збереженні значення getActivity().getApplicationContext()змінної екземпляра при створенні фрагмента, а потім використовувати цей контекст, коли вам потрібно в класі фрагмента. Цей контекст переживе фрагментарний загін.
Піовезан

8
Замість того, щоб обходити контекст програми, створіть статичний контекст у своєму класі Application та ініціалізуйте його onCreate (): MyApplication.sContext = getApplicationContext (); то ви можете отримати доступ до нього з будь-якої діяльності / фрагменту, не турбуючись про відсторонення.
Едуко

3
@milaniez: getActivityзавжди був доступний. Це getContextдодано в API 23.
mhsmith

130

Щоб виконати відповідь вище, ви можете змінити onAttachметод фрагмента:

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

3
Я рекомендую це, оскільки getActivity () повертає нуль, якщо onAttach ще не викликається.
arne.jans

9
Але майте на увазі, що при виклику onAttach () немає переглядів. Таким чином, ви нічого не можете зробити з поглядами!
Зордід

2
@iambox, що, якщо DatabaseHelperпотрібно FragmentActivityзамість цього Activity? Наприклад, для Adapter...
Jago

4
Якщо ви зберігаєте посилання на свою діяльність, onAttach(Activity activity)тоді вам слід випустити їїonDetach()
vovahost

3
onAttachМетод застарів,Overrides deprecated method in 'android.support.v4.app.Fragment'
Мухаммад Saqib

24

Завжди використовуйте метод getActivity (), щоб отримати контекст вашої доданої діяльності, але завжди пам’ятайте одне: Фрагменти трохи нестабільні та getActivityповертаються нульовими, а для цього завжди перевіряйте фрагмент методу isAdded (), перш ніж отримувати контекст getActivity().


15
Я б не сказав, що фрагменти є "злегка нестабільними", здається, цілком нормально повернення nuActivity () до нуля, коли фрагмент не належить до активності. Це припущення, що getActivity () "не повинен повернути null" (що неправильно), що зробить ваше додаток (а не клас Fragment) нестабільним.
personne3000

3
@ personne3000 Я хотів би почути більше. Коли фрагмент не належить до діяльності? Коли це відбувається і чому? Чи слід перевіряти isAdded () у фрагменті, щоб використовувати getActivity ()? Будь-яке правило?
Сотті

2
@Sotti Я закликаю вас створити для цього нове запитання (або шукати існуюче), оскільки ця конкретна тема трохи відрізняється від початкового питання. Ви можете подивитися на developer.android.com/guide/components/fragments.html#Lifecycle для отримання загальної інформації. В основному, до onAttach і після onDetach жодної активності. А між onAttach та onActivityCreate активом onCreate активність ще не називається. Використовуючи getActivity (), переконайтеся, що ваша діяльність вже створена, і подумайте, що буде, якщо вона була знищена або ваш фрагмент був від'єднаний.
personne3000

22

Найпростіший і найточніший спосіб отримати контекст фрагмента, який я знайшов, - це отримати його безпосередньо з методу, ViewGroupколи ви викликаєте onCreateViewпринаймні тут, ви впевнені, що не нульові для getActivity():

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

10
це контекст контейнера, я думаю ... не "цей контекст".
Fattie

2
@ AG1, будь ласка, поясніть, чому він розбив ваш код? Це поки що найкраще рішення, яке я маю
Мачадо

3
Насправді у dialogFragments контейнер може бути нульовим. Будь обережний!
Лукас Теске

Це рішення слід використовувати в onViewCreate, а не onCreateView.
Андреа Де Сімоне

13

Раніше я використовую , onAttach (Activity activity)щоб отримати contextвFragment

Проблема

onAttach (Activity activity)Метод був застарілим в рівні API 23.

Рішення

Тепер, щоб отримати контекст, Fragmentми можемо використовуватиonAttach (Context context)

onAttach (Context context)

  • Викликається, коли фрагмент вперше приєднаний до нього context. onCreate(Bundle)буде називатися після цього.

Документація

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

ЗРАЗДОВИЙ КОД

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

}

ПРИМІТКА

Ми також можемо використовувати , getActivity()щоб отримати contextв Fragments але getActivity()може повернутися , nullякщо ваше fragmentнині не додається до батькові чи матері activity,



6

Ви також можете отримати контекст з inflaterпараметра при переопределенні onCreateView.

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

5

Інший альтернативний підхід:

Ви можете отримати контекст, використовуючи:

getActivity().getApplicationContext();

5

отримати контекст всередині Фрагменту можна за допомогою getActivity():

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • Будьте уважні, щоб отримати Activityпов'язаний з фрагментом за допомогою getActivity(), ви можете використовувати його, але не рекомендується, що це призведе до витоку пам'яті.

Я думаю, що краще повинен бути Підхід отримання Activityвід onAttach()методу:

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

Ви не повинні використовувати getActivity у фрагменті, щоб отримати представлення, якщо цей вигляд не є частиною діяльності. Чому б ви надували погляд у фрагменті, навіть не посилаючись на нього нічого?
tyczj

Ця відповідь стосується чогось іншого, ви говорите про те, в якому режимі перегляду ви можете шукати перегляди. Activity.findViewByIdЦе лише зручний спосіб пошуку погляду в зареєстрованому представленні вмісту цієї діяльності (встановленому наскрізь setContentView). У правильному прикладі ви викликаєте View.findViewById, а не Activity.findViewById, і ви посилаєтесь на метод у правильному кореневому вікні. Зовсім інша проблема, і, очевидно, ви не зможете знайти свій погляд у вікні пошуку, який не містить цього виду.
JHH

3

getContext() прийшов в API 23. Замініть його на getActivity () скрізь у коді.

Подивіться, чи вона виправляє помилку. Спробуйте використовувати методи, які знаходяться між цільовим та мінімальним рівнем API, інакше ця помилка буде мати місце.


3

Оскільки рівень API 23 є, getContext()але якщо ви хочете підтримувати більш старі версії, ви можете використовувати, getActivity().getApplicationContext()хоча я все ж рекомендую використовувати версію підтримки, Fragmentяка є android.support.v4.app.Fragment.



2

Використовуйте фрагменти з бібліотеки підтримки -

android.support.v4.app.Fragment

а потім переосмислити

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

Таким чином ви можете бути впевнені, що контекст завжди буде ненульовим значенням.


2

У вас є різні варіанти:

  • Якщо ваш minSDK <= 21, то ви можете використовувати getActivity(), оскільки це a Context.
  • Якщо ваш minSDK> = 23, ви можете використовувати getContext().

Якщо вам не потрібно підтримувати старі версії, тоді перейдіть з getContext().


2

Для Котліна можна використовувати contextбезпосередньо фрагменти. Але в деяких випадках ви знайдете помилку на кшталт

Невідповідність типу: виведений тип - це контекст? але контекст очікувався

для цього ти можеш це зробити

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

Дякуємо за те, що скористався версією Kotlin, яка працює чудово, проте я намагаюся отримати Context для Picasso.get (), і він ніколи не працює, я спробував усе, що можу, із зразків вище, а також отримати контекст. У кращому випадку я отримую це повідомлення -Задано багато аргументів ... Будь ласка, допоможіть. val ctx = контекст?: повернути Picasso.get (ctx) .load (selectedGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage)
Ade

@Ade У своєму фрагменті спробуйте використовувати "активність !!" замість "ctx", і дайте мені знати, допомагає це чи ні
Kishan Solanki

@ KishanSolanki124. Дуже дякую за швидку відповідь. Я спробував вашу пропозицію, з тим же результатом - Не працює досі. Точний запит про помилку - Занадто багато аргументів для публічного відкритого задоволення get (): Picasso !. Це повідомлення змушує мене задуматися, можливо, щось інше є помилкою ?. З радістю знайшов спосіб продовжувати свою роботу, використовуючи Picasso, не отримуючи контексту. Знову дякую.
Аде



1

В ідеалі не потрібно використовувати глобали. У фрагменті є різні сповіщення, одне з яких є onActivityCreate. Ви можете отримати екземпляр активності в цьому фрагменті цього життєвого циклу.

Потім: ви можете знеструмлювати фрагмент, щоб отримати активність, контекст або контекст програми за вашим бажанням:

this.getActivity()дасть вам обробку діяльності this.getContext(), дасть вам обробку контексту this.getActivity().getApplicationContext(), дасть вам обробку контексту програми. Переважно використовувати контекст програми, передаючи його на db.


1

Простий спосіб - це використовувати getActivity(). Але я думаю, що основна плутанина використання getActivity()методу для отримання контексту є нульовим винятком покажчика.

Для цього спочатку зверніться до isAdded()методу, який визначить, додається він чи ні, а потім ми можемо скористатись getActivity()для отримання контексту Діяльності.


1
Чим це відрізняється від відповіді Анкура Чаддхарі ?
Пітер Мортенсен

1

Ви можете зателефонувати getActivity()або,

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

1

Ви можете використовувати метод getActivity () для отримання контексту або метод getContext ().

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

Я сподіваюся, що це допомагає!


1
Є й інші відповіді, які забезпечують питання ОП, і вони були опубліковані деякий час тому. Опублікувавши відповідь, дивіться: Як написати гарну відповідь? , переконайтесь, що ви додали або нове рішення, або істотно краще пояснення, особливо, відповідаючи на старіші запитання.
help-info.de

0

Метод getContext () допомагає використовувати контекст класу в діяльності з фрагментами.


0

Я думаю, ви можете використовувати

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

Також ви можете використовувати:

inflater.getContext();

але я вважаю за краще використовувати

getActivity()

або

getContext

0

Мені потрібен контекст для використання фрагмента arrayAdapter IN, коли я використовував помилку getActivity, але коли я замінюю його на getContext, він працює для мене

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

0

Ви можете використовувати getActivity()або getContextу фрагменті.

Документація

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

і

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

Професійний підказки

Перевіряйте завжди, if(getActivity!=null)оскільки це може бути недійсним, коли фрагмент не приєднаний до активності. Іноді виконання тривалої роботи в фрагменті (наприклад, отримання даних із спокою api) вимагає певного часу. і якщо користувач перейде до іншого фрагмента. Тоді getActivity буде нульовою. І ви отримаєте NPE, якщо ви не впоралися з цим.


Це документація методу getActivity (), просто щоб показати, що вони можуть бути недійсними. Тут mHost - це примірник FragmentHostCallbackкласу.
Хемрайдж

0

На вас фрагмент

((Name_of_your_Activity) getActivity()).helper

Про активність

DbHelper helper = new DbHelper(this);

0

Всередині фрагмент для зразка котліна комусь допоможе

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

якщо ви використовуєте прив'язку даних;

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

Там, де ініціалізується obliVView в onCreateView, як це

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.