Saya memiliki fragmen (F1) dengan metode publik seperti ini
public void asd() {
if (getActivity() == null) {
Log.d("yes","it is null");
}
}
dan ya ketika saya menyebutnya (dari Aktivitas), itu adalah nol ...
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();
Pasti sesuatu yang saya lakukan sangat salah, tetapi saya tidak tahu apa itu
getActivity()
. Juga, bagaimana Anda membuat fragmen? Apakah Anda memilikinya di layout.xml Anda?Jawaban:
commit
menjadwalkan transaksi, yaitu tidak terjadi langsung tetapi dijadwalkan sebagai bekerja pada utas utama saat berikutnya utas utama siap.Saya sarankan menambahkan
metode untuk Anda
Fragment
dan menempatkan titik istirahat di atasnya dan melihat ketika itu dipanggil relatif terhadap panggilan Andaasd()
. Anda akan melihat bahwa itu dipanggil setelah metode di mana Anda membuat panggilan untukasd()
keluar. TheonAttach
panggilan di manaFragment
melekat pada aktivitas dan dari titik inigetActivity()
akan kembali non-null (nb ada jugaonDetach()
panggilan).sumber
onCreateView
atauonActivityCreated
metode. Saya mempertanyakan mengapa ASD () perlu dipanggil ketika itu dilakukan dalam posting pertanyaan.commitNow()
Cara terbaik untuk menghilangkannya adalah menyimpan referensi aktivitas saat onAttach dipanggil dan menggunakan referensi aktivitas di mana pun dibutuhkan, misalnya
sumber
onDestroy()
danonDetach()
karenaonDestroy()
tidak dijamin dipanggil.Activity
jika kita tidak membatalkannyaonDestroy()
?Ini terjadi ketika Anda memanggil
getActivity()
utas lain yang selesai setelah fragmen telah dihapus. Kasus khas adalah panggilangetActivity()
(mis. Untuk aToast
) saat permintaan HTTP selesai (onResponse
misalnya).Untuk menghindari ini, Anda bisa menentukan nama bidang
mActivity
dan menggunakannyagetActivity()
. Bidang ini dapat diinisialisasi dalam metode Fragmen onAttach () sebagai berikut:Dalam proyek saya, saya biasanya menentukan kelas dasar untuk semua Fragmen saya dengan fitur ini:
Selamat coding,
sumber
Activity
dari utas lainnya sama sekali. Anda tidak dapat melakukan apa pun dengan itu, bahkan tidak menunjukkan Toast. Jadi Anda harus mentransfer pekerjaan ke utas utama terlebih dahulu, atau tidak menggunakan Activity sama sekali.Jawaban lain yang menyarankan menyimpan referensi ke aktivitas di onAttach hanya menyarankan bandaid untuk masalah sebenarnya. Ketika getActivity mengembalikan nol, itu berarti Fragmen tidak dilampirkan ke Aktivitas. Paling umum hal ini terjadi ketika Aktivitas telah hilang karena rotasi atau Aktivitas selesai tetapi Fragmen masih memiliki semacam pendengar panggilan balik yang terdaftar. Ketika pendengar dipanggil jika Anda perlu melakukan sesuatu dengan Kegiatan tetapi Kegiatan itu hilang tidak banyak yang bisa Anda lakukan. Dalam kode Anda, Anda hanya harus memeriksa
getActivity() != null
dan jika tidak ada maka jangan lakukan apa-apa. Jika Anda menyimpan referensi ke Aktivitas yang hilang, Anda mencegah agar Aktivitas tidak menjadi sampah yang dikumpulkan. Segala hal UI yang mungkin Anda coba lakukan tidak akan terlihat oleh pengguna. Saya bisa membayangkan beberapa situasi di mana dalam pemanggil panggilan balik Anda mungkin ingin memiliki Konteks untuk sesuatu yang tidak terkait UI, dalam kasus-kasus itu mungkin lebih masuk akal untuk mendapatkan konteks Aplikasi. Perhatikan bahwa satu-satunya alasanonAttach
trik ini bukan kebocoran memori yang besar adalah karena biasanya setelah pemanggil panggil balik dijalankan itu tidak akan diperlukan lagi dan dapat menjadi sampah yang dikumpulkan bersama dengan Fragment, semua View-nya dan konteks Activity. Jika kamusetRetainInstance(true)
ada kemungkinan lebih besar kebocoran memori karena bidang Aktivitas juga akan dipertahankan tetapi setelah rotasi yang bisa menjadi Aktivitas sebelumnya bukan yang sekarang.sumber
Sejak Android API level 23, onAttach (Aktivitas aktivitas) telah ditinggalkan. Anda perlu menggunakan onAttach (Konteks konteks). http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)
Aktivitas adalah konteks, jadi jika Anda bisa mengecek konteksnya adalah sebuah Aktivitas dan melemparkannya jika perlu.
sumber
PJL benar. Saya telah menggunakan sarannya dan inilah yang telah saya lakukan:
variabel global yang didefinisikan untuk fragmen:
private final Object attachingActivityLock = new Object();
private boolean syncVariable = false;
diimplementasikan
3. Saya membungkus fungsi saya, di mana saya perlu memanggil getActivity (), di utas, karena jika itu akan berjalan pada utas utama, saya akan memblokir utas dengan langkah 4. dan onAttach () tidak akan pernah dipanggil.
4. dalam fungsi saya di mana saya perlu memanggil getActivity (), saya menggunakan ini (sebelum panggilan getActivity ())
Jika Anda memiliki beberapa pembaruan UI, ingatlah untuk menjalankannya di utas UI. Saya perlu memperbarui ImgeView jadi saya lakukan:
sumber
Urutan panggilan dipanggil setelah commit ():
Saya perlu melakukan beberapa pekerjaan yang melibatkan beberapa Tampilan, jadi onAttach () tidak bekerja untuk saya; itu jatuh. Jadi saya memindahkan bagian dari kode saya yang mengatur beberapa params di dalam metode yang disebut setelah komit () (1.), kemudian bagian lain dari kode yang menangani tampilan di dalam onCreateView () (3.).
sumber
Saya menggunakan OkHttp dan saya baru saja menghadapi masalah ini.
Untuk bagian pertama @thucnguyen berada di jalur yang benar .
Beberapa panggilan HTTP sedang dieksekusi bahkan setelah aktivitas telah ditutup (karena itu bisa memakan waktu beberapa saat untuk permintaan HTTP diselesaikan). Saya kemudian, melalui
HttpCallback
mencoba memperbarui beberapa bidang Fragmen dan mendapatnull
pengecualian ketika mencobagetActivity()
.IMO solusinya adalah untuk mencegah panggilan balik terjadi ketika fragmen tidak lagi hidup lagi (dan itu tidak hanya dengan Okhttp).
Cara mengatasinya: Pencegahan.
Jika Anda melihat siklus fragmen (info lebih lanjut di sini ), Anda akan melihat ada
onAttach(Context context)
danonDetach()
metode. Ini dipanggil setelah Fragmen milik aktivitas dan sesaat sebelum berhenti menjadi masing-masing.Itu berarti bahwa kita dapat mencegah panggilan balik itu terjadi dengan mengendalikannya dalam
onDetach
metode.sumber
Di mana Anda memanggil fungsi ini? Jika Anda memanggilnya di konstruktor
Fragment
, ia akan kembalinull
.Panggil saja
getActivity()
ketika metodeonCreateView()
ini dijalankan.sumber
Lakukan sebagai berikut. Saya pikir ini akan sangat membantu Anda.
sumber
Mereka yang masih memiliki masalah dengan onAttach (Aktivitas aktivitas), Itu baru saja berubah menjadi Konteks -
Dalam kebanyakan kasus, menyimpan konteks akan cukup untuk Anda - misalnya jika Anda ingin mendapatkan getResources () Anda dapat melakukannya langsung dari konteksnya. Jika Anda masih perlu membuat konteks ke dalam Aktivitas Anda, lakukanlah -
Seperti yang disarankan oleh user1868713.
sumber
Anda bisa menggunakan onAttach atau jika Anda tidak ingin memakai onAttach di mana-mana maka Anda bisa meletakkan metode yang mengembalikan ApplicationContext pada kelas App utama:
Setelah itu Anda dapat menggunakannya kembali di mana-mana di seluruh proyek Anda, seperti ini:
Tolong beri tahu saya jika ini tidak berhasil untuk Anda.
sumber
Solusi bagus lainnya adalah menggunakan LiveData Android dengan arsitektur MVVM. Anda akan mendefinisikan objek LiveData di dalam ViewModel Anda dan mengamatinya di fragmen Anda, dan ketika nilai LiveData diubah, itu akan memberi tahu pengamat Anda (fragmen dalam kasus ini) hanya jika fragmen Anda dalam keadaan aktif, sehingga dijamin bahwa Anda akan akan membuat UI Anda berfungsi dan mengakses aktivitas hanya ketika fragmen Anda dalam keadaan aktif. Ini adalah salah satu keuntungan yang hadir dengan LiveData
Tentu saja ketika pertanyaan ini pertama kali ditanyakan, tidak ada LiveData. Saya meninggalkan jawaban ini di sini karena seperti yang saya lihat, masih ada masalah ini dan itu bisa membantu seseorang.
sumber
Panggil metode getActivity () di dalam onActivityCreated ()
sumber