Menggunakan konteks dalam sebuah fragmen


664

Bagaimana saya bisa mendapatkan konteks dalam sebuah fragmen?

Saya perlu menggunakan database saya yang konstruktornya mengambil konteks, tetapi getApplicationContext()danFragmentClass.this tidak bekerja jadi apa yang bisa saya lakukan?

Konstruktor basis data

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

Jawaban:


1313

Anda dapat menggunakan getActivity(), yang mengembalikan aktivitas yang terkait dengan a fragment.
Aktivitasnya adalah context (sejak Activitymeluas Context) .


212
getActivity () dapat mengembalikan null jika dipanggil sebelum onAttach masing-masing fragmen.
arne.jans

4
Saya membaca blog Google ini tentang kebocoran memori ... android-developers.blogspot.com/2009/01/… . Jika saya menggunakan metode getActivity () apakah aplikasi tidak berisiko bocor memori? Blog menyarankan "Coba gunakan aplikasi konteks daripada aktivitas konteks" yang sebenarnya tidak mungkin karena getApplicationContext () hanya berfungsi untuk kelas Activity dan bukan kelas Fragment.
Simon

40
Solusi untuk masalah fragmen terpisah adalah menyimpan nilai getActivity().getApplicationContext()dalam variabel instan ketika fragmen dibuat dan kemudian menggunakan konteks itu kapan pun Anda inginkan di dalam kelas fragmen. Konteks itu akan bertahan dari detasemen fragmen.
Piovezan

8
Alih-alih meneruskan konteks aplikasi, buat konteks statis di dalam kelas Aplikasi Anda dan inisialisasi di onCreate (): MyApplication.sContext = getApplicationContext (); maka Anda dapat mengaksesnya dari aktivitas / fragmen apa pun tanpa khawatir tentang detasemen.
Eduko

3
@milaniez: getActivityselalu tersedia. Itu getContextyang ditambahkan di API 23.
mhsmith

130

Untuk melakukan seperti jawaban di atas, Anda dapat mengganti onAttachmetode fragmen:

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

3
Saya akan merekomendasikan ini, karena getActivity () mengembalikan null jika onAttach belum dipanggil.
arne.jans

9
Tapi, perlu diingat, ketika onAttach () dipanggil, tidak ada tampilan. Jadi, Anda belum bisa melakukan apa pun dengan tampilan!
Zordid

2
@ iambox bagaimana jika DatabaseHelperdibutuhkan FragmentActivitybukan Activity? Misalnya, untuk Adapter...
Jago

4
Jika Anda menyimpan referensi untuk aktivitas Anda di onAttach(Activity activity)maka Anda harus merilisnya dionDetach()
vovahost

3
The onAttachMetode telah usang,Overrides deprecated method in 'android.support.v4.app.Fragment'
Muhammad Saqib

24

Selalu gunakan metode getActivity () untuk mendapatkan konteks aktivitas terlampir Anda, tetapi selalu ingat satu hal: Fragmen sedikit tidak stabil dan getActivitymengembalikan null beberapa kali, jadi untuk itu, selalu periksa metode fragmen isAdded () sebelum mendapatkan konteks getActivity().


15
Saya tidak akan mengatakan bahwa fragmen "sedikit tidak stabil", tampaknya cukup normal bagi getActivity () untuk mengembalikan nol ketika fragmen itu bukan dari suatu aktivitas. Diasumsikan bahwa getActivity () "tidak boleh mengembalikan null" (yang salah) yang akan membuat aplikasi Anda (dan bukan kelas Fragmen) tidak stabil.
personne3000

3
@ personne3000 Saya ingin mendengar lebih banyak. Kapan sebuah fragmen bukan milik suatu Kegiatan? Kapan ini terjadi dan mengapa? Haruskah kita memeriksa isAdded () di fragmen untuk menggunakan getActivity ()? Ada aturan praktis?
Sotti

2
@ Sotti Saya mendorong Anda untuk membuat pertanyaan baru untuk ini (atau mencari yang sudah ada), karena subjek khusus ini sedikit berbeda dari pertanyaan awal. Anda dapat melihat di developer.android.com/guide/components/fragments.html#Lifecycle untuk informasi umum. Pada dasarnya, sebelum onAttach dan setelah onDetach, tidak ada aktivitas. Dan antara onAttach dan onActivityCreated, aktivitas onCreate belum dipanggil. Saat menggunakan getActivity (), pastikan aktivitas Anda sudah dibuat, dan pikirkan apa yang akan terjadi jika dihancurkan atau fragmen Anda terlepas.
personne3000

22

Cara termudah dan paling tepat untuk mendapatkan konteks fragmen yang saya temukan adalah untuk mendapatkannya langsung dari ViewGroupsaat Anda memanggil onCreateViewmetode setidaknya di sini Anda yakin tidak akan mendapatkan null untuk getActivity():

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

10
itulah konteks wadahnya, saya pikir ... bukan "konteks ini".
Fattie

2
@ AG1, bisakah Anda menjelaskan mengapa kode Anda rusak? Sejauh ini solusi terbaik yang saya punya
Machado

3
Sebenarnya pada dialogFragments, wadahnya bisa nol. Hati-hati!
Lucas Teske

Solusi ini harus digunakan di onViewCreated, bukan onCreateView.
Andrea De Simone

13

Sebelumnya saya menggunakan onAttach (Activity activity)untuk mendapatkan contextdiFragment

Masalah

The onAttach (Activity activity)Metode ini usang dalam API tingkat 23.

Larutan

Sekarang untuk mendapatkan konteks Fragmentbisa kita gunakanonAttach (Context context)

onAttach (Context context)

  • Disebut ketika sebuah fragmen pertama kali dilampirkan padanya context. onCreate(Bundle)akan dipanggil setelah ini.

Dokumentasi

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

KODE SAMPEL

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

}

CATATAN

Kita juga bisa menggunakan getActivity()untuk mendapatkan contextdi Fragments tetapi getActivity()dapat kembali nulljika Anda yang fragmentsaat ini tidak melekat pada orang tua activity,


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

6

Anda juga bisa mendapatkan konteks dari inflaterparameter, saat mengganti onCreateView.

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

5

Pendekatan alternatif lain adalah:

Anda bisa mendapatkan konteksnya menggunakan:

getActivity().getApplicationContext();

5

untuk mendapatkan konteks di dalam Fragmen akan dimungkinkan menggunakan getActivity():

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • Hati-hati, untuk mendapatkan Activityketerkaitan dengan fragmen yang digunakan getActivity(), Anda dapat menggunakannya tetapi tidak disarankan akan menyebabkan kebocoran memori.

Saya pikir pendekatan yang lebih baik harus diperoleh Activitydari onAttach()metode:

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

Anda tidak boleh menggunakan getActivity dalam sebuah fragmen untuk mendapatkan tampilan kecuali jika pandangan itu tetap merupakan bagian dari aktivitas. Mengapa Anda mengembang tampilan dalam fragmen kemudian bahkan tidak referensi apa pun darinya?
tyczj

Jawaban ini adalah tentang sesuatu yang berbeda, Anda berbicara tentang tampilan mana yang harus dicari untuk mencari tampilan. Activity.findViewByIdIni hanyalah metode praktis untuk mencari tampilan dalam tampilan konten terdaftar aktivitas tersebut (disetel setContentView). Dalam contoh Anda yang benar, Anda menelepon View.findViewById, bukan Activity.findViewById, dan Anda memanggil metode pada tampilan root yang benar . Masalah yang sama sekali berbeda, dan jelas Anda tidak akan dapat menemukan tampilan Anda dalam tampilan hiearchy yang tidak memiliki tampilan itu.
JHH

3

getContext() datang di API 23. Ganti dengan getActivity () di mana pun dalam kode.

Lihat apakah itu memperbaiki kesalahan. Cobalah untuk menggunakan metode yang berada di antara target dan tingkat API minimun, jika tidak kesalahan ini akan terjadi.


3

Karena API level 23 ada getContext()tetapi jika Anda ingin mendukung versi yang lebih lama Anda dapat menggunakan getActivity().getApplicationContext()sementara saya masih merekomendasikan menggunakan versi dukungan Fragmentyang ada android.support.v4.app.Fragment.


2

getActivity() adalah anak dari Konteks sehingga harus bekerja untuk Anda


2

Gunakan fragmen dari Perpustakaan Dukungan -

android.support.v4.app.Fragment

lalu timpa

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

Dengan cara ini Anda dapat yakin bahwa konteks akan selalu menjadi nilai yang bukan nol.


2

Anda memiliki opsi berbeda:

  • Jika minSDK Anda <= 21, maka Anda dapat menggunakan getActivity(), karena ini adalah a Context.
  • Jika minSDK Anda>> 23, maka Anda dapat menggunakan getContext().

Jika Anda tidak perlu mendukung versi lama maka ikuti getContext().


2

Untuk Kotlin Anda dapat menggunakan contextlangsung dalam fragmen. Tetapi dalam beberapa cased Anda akan menemukan kesalahan seperti

Jenis ketidakcocokan: tipe disimpulkan adalah Konteks? tapi diharapkan konteksnya

untuk itu kamu bisa melakukan ini

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

Terima kasih telah menggunakan versi Kotlin, yang berfungsi dengan baik, namun saya mencoba untuk mendapatkan Konteks untuk Picasso.get (), dengan itu dan tidak pernah berhasil, saya telah mencoba semua yang saya bisa dari sampel di atas juga untuk mendapatkan konteks. Paling-paling saya mendapatkan pesan ini -Terlalu banyak argumen yang terlewati ... Tolong bantu. val ctx = konteks?: return Picasso.get (ctx) .load (terpilihGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage)
Ade

@Ade Dalam fragmen Anda, coba gunakan "aktivitas !!" alih-alih "ctx" dan beri tahu saya ini membantu atau tidak
Kishan Solanki

@ KishanSolanki124. Terima kasih banyak atas tanggapan cepatnya. Saya mencoba saran Anda, dengan hasil yang sama - Tidak berfungsi. Prompt galat yang tepat adalah - Terlalu banyak argumen untuk mendapatkan kesenangan publik (): Picasso! Pesan ini membuat saya berpikir, mungkin ada kesalahan lain? Namun senangnya, menemukan cara untuk melanjutkan pekerjaan saya dengan menggunakan Picasso tanpa konteks. Terima kasih lagi.
Ade


2

Dengan API 29+ di Kotlin, saya harus melakukannya

activity?.applicationContext!!

Contohnya adalah

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

Konteks! = ApplicationContext
Gabriele Mariotti

1

Idealnya, Anda tidak perlu menggunakan global. Fragmen ini memiliki notifikasi berbeda, salah satunya onActivityCreated. Anda bisa mendapatkan contoh aktivitas dalam peristiwa siklus hidup fragmen ini.

Kemudian: Anda dapat melakukan dereferensi fragmen untuk mendapatkan konteks aktivitas, konteks atau aplikasi sesuai keinginan:

this.getActivity()akan memberi Anda pegangan untuk aktivitas this.getContext()akan memberi Anda pegangan untuk konteks this.getActivity().getApplicationContext()akan memberi Anda pegangan untuk konteks aplikasi. Anda sebaiknya menggunakan konteks aplikasi ketika meneruskannya ke db.


1

Cara sederhana adalah menggunakan getActivity(). Tapi saya pikir kebingungan utama menggunakan getActivity()metode untuk mendapatkan konteks di sini adalah pengecualian null pointer.

Untuk ini, periksa terlebih dahulu dengan isAdded()metode yang akan menentukan apakah itu ditambahkan atau tidak, dan kemudian kita dapat menggunakan getActivity()untuk mendapatkan konteks Kegiatan.



1

Anda dapat menelepon getActivity()atau,

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

1

Anda dapat menggunakan metode getActivity () untuk mendapatkan konteks atau Anda dapat menggunakan metode getContext ().

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

Saya harap ini membantu!


1
Ada jawaban lain yang memberikan pertanyaan OP, dan mereka diposting beberapa waktu lalu. Saat mengirim jawaban, lihat: Bagaimana saya menulis jawaban yang baik? , harap pastikan Anda menambahkan solusi baru, atau penjelasan yang jauh lebih baik, terutama saat menjawab pertanyaan yang lebih lama.
help-info.de

0

Metode getContext () membantu untuk menggunakan Konteks kelas dalam aktivitas fragmen.


0

Saya pikir Anda bisa menggunakannya

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

Anda juga dapat menggunakan:

inflater.getContext();

tapi saya lebih suka menggunakan

getActivity()

atau

getContext

0

Saya perlu konteks untuk menggunakan arrayAdapter IN fragmen, ketika saya menggunakan getActivity error terjadi tetapi ketika saya menggantinya dengan getContext berfungsi untuk saya

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

0

Anda dapat menggunakan getActivity()atau getContextdalam Fragmen.

Dokumentasi

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

dan

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

Kiat pro

Periksa selalu if(getActivity!=null)karena itu bisa nol ketika fragmen tidak dilampirkan ke aktivitas. Kadang-kadang melakukan operasi lama dalam fragmen (seperti mengambil data dari api sisanya) membutuhkan waktu. dan jika pengguna menavigasi ke fragmen lain. Maka getActivity akan menjadi nol. Dan Anda akan mendapatkan NPE jika Anda tidak menanganinya.


Ini adalah dokumentasi metode getActivity (), hanya untuk menunjukkan bahwa ini bisa menjadi nol. Di sini mHost adalah turunan dari FragmentHostCallbackkelas.
Khemraj

0

Pada fragmen Anda

((Name_of_your_Activity) getActivity()).helper

Aktifitas Aktif

DbHelper helper = new DbHelper(this);

0

Fragmen di dalam untuk sampel kotlin akan membantu seseorang

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

jika Anda menggunakan penyatuan data;

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

Di mana bindingView diinisialisasi di onCreateView seperti ini

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.