Saya telah melihat dua praktik umum untuk membuat Instansi baru dalam aplikasi:
Fragment newFragment = new MyFragment();
dan
Fragment newFragment = MyFragment.newInstance();
Opsi kedua menggunakan metode statis newInstance()
dan umumnya berisi metode berikut.
public static Fragment newInstance()
{
MyFragment myFragment = new MyFragment();
return myFragment;
}
Pada awalnya, saya pikir manfaat utama adalah fakta bahwa saya dapat membebani metode newInstance () untuk memberikan fleksibilitas ketika membuat instance Fragmen baru - tetapi saya juga bisa melakukan ini dengan membuat konstruktor yang kelebihan beban untuk Fragmen.
Apakah saya melewatkan sesuatu?
Apa manfaat dari satu pendekatan di atas yang lain? Atau hanya praktik yang baik?
android
android-fragments
Graham Smith
sumber
sumber
Jawaban:
Jika Android memutuskan untuk membuat ulang Fragmen Anda nanti, itu akan memanggil konstruktor no-argumen fragmen Anda. Jadi kelebihan konstruktor bukanlah solusi.
Dengan itu dikatakan, cara untuk mengirimkan barang ke Fragmen Anda sehingga mereka tersedia setelah Fragment diciptakan kembali oleh Android adalah dengan mengirimkan bundel ke
setArguments
metode.Jadi, misalnya, jika kami ingin memberikan bilangan bulat ke fragmen kami akan menggunakan sesuatu seperti:
Dan nanti di Fragmen
onCreate()
Anda dapat mengakses integer itu dengan menggunakan:Bundel ini akan tersedia bahkan jika Fragmennya dibuat ulang oleh Android.
Perhatikan juga:
setArguments
hanya dapat dipanggil sebelum Fragmen dilampirkan ke Aktivitas.Pendekatan ini juga didokumentasikan dalam referensi pengembang android: https://developer.android.com/reference/android/app/Fragment.html
sumber
Satu-satunya manfaat dalam menggunakan
newInstance()
yang saya lihat adalah sebagai berikut:Anda akan memiliki satu tempat di mana semua argumen yang digunakan oleh fragmen dapat digabungkan dan Anda tidak harus menulis kode di bawah ini setiap kali Anda membuat fragmen.
Ini cara yang bagus untuk memberi tahu kelas lain argumen apa yang diharapkan akan berfungsi dengan baik (meskipun Anda harus dapat menangani kasus jika tidak ada argumen yang dibundel dalam contoh fragmen).
Jadi, pendapat saya adalah menggunakan statik
newInstance()
untuk membuat fragmen adalah praktik yang baik.sumber
Ada juga cara lain:
sumber
instantiate()
Creates a new instance of a Fragment with the given class name. This is the same as calling its empty constructor.
Sementara @yydl memberikan alasan kuat mengapa
newInstance
metode ini lebih baik:masih sangat mungkin menggunakan konstruktor . Untuk melihat mengapa ini, pertama-tama kita perlu melihat mengapa solusi di atas digunakan oleh Android.
Sebelum sebuah fragmen dapat digunakan, sebuah instance dibutuhkan. Android memanggil
YourFragment()
( konstruktor tanpa argumen ) untuk membuat instance fragmen. Di sini konstruktor kelebihan beban apa pun yang Anda tulis akan diabaikan, karena Android tidak dapat mengetahui mana yang akan digunakan.Dalam masa Aktivitas, fragmen dibuat seperti di atas dan dihancurkan beberapa kali oleh Android. Ini berarti bahwa jika Anda menempatkan data dalam objek fragmen itu sendiri, itu akan hilang setelah fragmen dihancurkan.
Untuk mengatasinya, android meminta Anda menyimpan data menggunakan
Bundle
(panggilansetArguments()
), yang kemudian dapat diakses dariYourFragment
. Argumenbundle
dilindungi oleh Android, dan karenanya dijamin akan tetap ada .Salah satu cara untuk mengatur bundel ini adalah dengan menggunakan
newInstance
metode statis :Namun, seorang konstruktor:
dapat melakukan hal yang persis sama dengan
newInstance
metode.Secara alami, ini akan gagal, dan merupakan salah satu alasan Android ingin Anda menggunakan
newInstance
metode ini:Sebagai penjelasan lebih lanjut, inilah Kelas Fragmen Android:
Perhatikan bahwa Android meminta agar argumen ditetapkan hanya pada konstruksi, dan menjamin bahwa ini akan dipertahankan.
EDIT : Seperti yang ditunjukkan dalam komentar oleh @JHH, jika Anda menyediakan konstruktor khusus yang memerlukan beberapa argumen, maka Java tidak akan memberikan fragmen Anda dengan konstruktor default no arg . Jadi ini akan mengharuskan Anda untuk mendefinisikan konstruktor no arg , yang merupakan kode yang dapat Anda hindari dengan
newInstance
metode pabrik.EDIT : Android tidak lagi mengizinkan konstruktor yang kelebihan beban untuk fragmen. Anda harus menggunakan
newInstance
metode ini.sumber
Saya tidak setuju dengan jawaban yydi yang mengatakan:
Saya pikir ini adalah solusi dan yang bagus, inilah alasan mengapa ini dikembangkan oleh bahasa inti Java.
Benar bahwa sistem Android dapat menghancurkan dan membuat ulang
Fragment
. Jadi Anda bisa melakukan ini:Ini akan memungkinkan Anda untuk menarik
someInt
dari yanggetArguments()
terakhir aktif, bahkan jikaFragment
telah diciptakan ulang oleh sistem. Ini adalah solusi yang lebih elegan daripadastatic
konstruktor.Untuk pendapat saya
static
konstruktor tidak berguna dan tidak boleh digunakan. Juga mereka akan membatasi Anda jika di masa depan Anda ingin memperpanjang iniFragment
dan menambahkan lebih banyak fungsi ke konstruktor. Denganstatic
konstruktor Anda tidak dapat melakukan ini.Memperbarui:
Android menambahkan inspeksi yang menandai semua konstruktor non-default dengan kesalahan.
Saya sarankan untuk menonaktifkannya, untuk alasan yang disebutkan di atas.
sumber
Beberapa kode kotlin :
Dan Anda bisa mendapatkan argumen dengan ini:
sumber
Praktik terbaik untuk instance fragmen dengan argumen di android adalah memiliki metode pabrik statis di fragmen Anda.
Anda harus menghindari pengaturan bidang Anda dengan contoh fragmen. Karena setiap kali sistem android membuat ulang fragmen Anda, jika terasa bahwa sistem membutuhkan lebih banyak memori, daripada itu akan membuat ulang fragmen Anda dengan menggunakan konstruktor tanpa argumen.
Anda dapat menemukan lebih banyak info tentang praktik terbaik untuk membuat instance fragmen dengan argumen di sini.
sumber
Karena pertanyaan tentang praktik terbaik, saya akan menambahkan, itu sering kali ide yang baik untuk menggunakan pendekatan hybrid untuk membuat fragmen ketika bekerja dengan beberapa layanan web REST
Kami tidak dapat melewatkan objek yang kompleks, misalnya beberapa model Pengguna, untuk kasus menampilkan fragmen pengguna
Tapi yang bisa kita lakukan adalah mengecek
onCreate
pengguna itu! = Nol dan jika tidak - maka bawalah dia dari lapisan data, jika tidak - gunakan yang ada.Dengan cara ini kita mendapatkan kedua kemampuan untuk membuat ulang oleh userId dalam hal rekreasi fragmen oleh Android dan ketangkasan untuk tindakan pengguna, serta kemampuan untuk membuat fragmen dengan memegang ke objek itu sendiri atau hanya id itu
Sesuatu menyukai ini:
sumber
User user = /*...*/
letakkan pengguna pada bundel:Bundle bundle = new Bundle(); bundle.putParcelable("some_user", user);
dan dapatkan pengguna dari argumen:User user = getArguments().getParcelable("some_user");
Objek harus mengimplementasikan antarmuka Parcelable. tautangunakan kode ini 100% memperbaiki masalah Anda
masukkan kode ini di firstFragment
sampel ini mengirim data boolean
dan di SecendFragment
kode bahagia
sumber
Cara terbaik untuk membuat instance fragmen adalah menggunakan metode Fragment.instantiate default atau membuat metode pabrik untuk instantiate fragmen
Perhatian: selalu buat satu konstruktor kosong dalam fragmen yang lain sementara mengembalikan memori fragmen akan membuang pengecualian run-time.
sumber
Akhir-akhir ini saya di sini. Tapi kadang-kadang saya tahu itu mungkin sedikit membantu Anda.
Jika Anda menggunakan Java, tidak ada banyak yang berubah. Tetapi untuk pengembang kotlin, berikut adalah beberapa cuplikan berikut yang menurut saya dapat membuat Anda menjadi ruang bawah tanah untuk dijalankan:
Selamat coding.
sumber
setArguments()
tidak berguna. Itu hanya membawa kekacauan.sumber
onViewCreated
ruang lingkup. Ini kenyamanan saya kira, banyak cara untuk melakukan hal yang sama. Juga ini adalah cara mudah untuk memeriksa pembaruan yang dilakukan oleh pengguna (bandingkan bundelgetArguments
dan bundel darionSaveInstanceState
)getArguments
hal-hal witout . Bagaimana denganonViewCreated
ruang lingkup ... Kita dapat mengembalikan bundel status di sana. Tapi saya lebih suka membuatonCreateView
ringan dan cepat dan melakukan semua inisialisasi berat di dalamonActivityCreated
karenaFragment.getActivity()
kadang-kadang ingin kembalinull
dan karenaonAttach()
perubahan dalam versi baru API 23.set
danget
Arguments
masuksaveInstanceState
. Anda pada dasarnya melakukan hal yang sama yang dilakukan "di bawah tenda"saveInstanceState
adalah "di bawah tenda". Dan penggunaanArguments
duplikasi fungsi yang membuat Anda memeriksa ulang:Arguments
nilai pertama dan kemudiansaveInstanceState
nilai. Karena Anda harus menggunakansaveInstanceState
cara apa pun. Bagaimana denganArguments
... mereka tidak perlu.Saya yakin saya punya solusi yang lebih sederhana untuk ini.
sumber