Mengapa saya tidak menggunakan SharedViewModel untuk fragmen?

Habr, halo!

Tugas mengatur interaksi antara fragmen sangat umum. Pada pandangan pertama, ShareViewModel sangat bagus untuk ini. Kami membuat ViewModel dengan pemilik = aktivitas kami, di mana fragmen kami ditampilkan, dan memasukkan ViewModel ini ke dalam setiap fragmen. Karena pemilik ViewModel adalah aktivitas, fragmen mendapatkan instance yang sama dari ViewModel, yang memungkinkan mereka untuk bertukar data, metode panggilan, dll. Ini tautan dari dokumentasi .

Gambar di bawah ini menunjukkan skema interaksi 3 fragmen.

gambar

Itu apa yang kami lakukan: di setiap fragmen kami mendapatkan SharedViewModel dari fragmen-fragmen yang kami perlukan untuk berinteraksi ...

Dan ini bukan solusi terbaik, menurut saya. Karena:

  1. *VM. ViewModel View. ViewModel LiveData, View, .. ViewModel - , View.
  2. SharedViewModel — . , SharedViewModel , , . - .
  3. SharedViewModel, . , , .

SharedViewModel hanya dapat digunakan ketika ada beberapa fragmen yang sama persis dengan data yang sama. Dalam praktik saya, tidak ada skenario seperti itu. Mungkin ada dua fragmen identik, tetapi keadaan ViewModel masing-masing berbeda, SharedViewModel tidak valid untuk mereka.

SharedViewModel membawa banyak masalah. Anda mulai bingung, semuanya ditumbuhi dependensi, kodenya rumit. Jauh lebih mudah untuk bekerja ketika Fragment + ViewModel adalah kotak hitam.

Solusi apa yang bisa ditawarkan?

Layanan sederhana yang setiap fragmen berinteraksi dengan caranya sendiri.

gambar

Layanan ini harus dilewati di dalam setiap ViewModel. Berkat DI dan ruang lingkup (Belati, Koin, yang lainnya) ini dapat dilakukan dengan mudah dan sederhana. Jika layanan harus hidup dalam konteks suatu Aktivitas, buatlah dalam Lingkup Kegiatan ini dan berikan ke setiap ViewModel.

Lihat apa yang terjadi: kami menghapus semua SharedViewModel dari fragmen. Setiap fragmen sekarang tidak tahu apa-apa tentang fragmen lainnya. Jika kami ingin menambahkan fragmen baru ke skema ini, maka kami hanya perlu menghubungkan viewModel D dengan layanan kami dan hanya itu. Jika fragmen tersebut merespons perubahan dalam beberapa properti layanan - berlangganan saja. Kita tidak perlu lagi memahami ViewModels orang lain. Dan layanan ini akan jauh lebih sederhana daripada ViewModel mana pun, akan lebih mudah untuk memahami layanan ini.

Tampaknya tidak banyak fragmen yang berinteraksi di satu layar. Di telepon - mungkin. Di tablet - Anda tidak bisa mengatakan itu lagi. Dan FragmentContainerView membantu menggunakan fragmen dalam tata letak apa pun, yang sangat nyaman jika aplikasi memiliki banyak komponen umum dengan siklus hidup.

Bonus: bagaimana cara membuat fragmen?


Seperti ini: SomeFragment ()

Dan bagaimana dengan parameternya?

Dengan munculnya ViewModel, saya tidak menggunakan parameter. Saya tidak meneruskan apa pun ke fragmen melalui bundel (Android Studio masih menawarkan untuk membuat fragmen dengan argumen dan membuat fragmen melalui metode statis), saya tidak menggunakan Safety NavArgs untuk Komponen Navigasi .

Semua hal ini membuat fragmen dikondisikan. Kami tidak bisa hanya mengambil fragmen seperti itu dan menambahkannya ke ViewPager, misalnya. Orang harus berpikir bagaimana cara melewati parameter. Atau contoh lain: Anda membuat fragmen dengan parameter, bekerja di dalamnya, data telah berubah, fragmen sudah menunjukkan sesuatu yang lain. Kami mengubah konfigurasi perangkat (terbalik), fragmen dibuat lagi dengan parameter yang ketinggalan zaman, sementara ViewModel sudah berisi data lain. Dan aktualisasi parameter, dll dimulai.

Saya menghapus semua ini di ViewModel. Saya menggunakan layanan yang sama di mana saya melewati parameter. Ini bekerja seperti Safety NavArgs. ViewModel meminta parameter dari layanan dengan jenis kelas parameter. Setelah berhasil mengambil parameter, layanan menghapusnya (berfungsi seperti Push / Pop).

Ini segera memecahkan masalah mengubah konfigurasi: fragmen itu dibuat lagi, dan Model View sudah dengan data saat ini, semua yang diperlukan adalah untuk menghubungkannya dengan Tampilan.

Ada juga masalah ketika meneruskan parameter melalui bundel - ini merupakan kelebihan dari jumlah yang diizinkan. Jika jumlah data yang ditransfer lebih dari 500 kb., Maka aplikasi mungkin macet karena pengecualian di dalam Binder.java. Hal ini menyebabkan penciptaan berbagai perpustakaan yang mengirimkan parameter melalui SD, yang tidak terlalu cepat dibandingkan dengan menggunakan RAM.

Secara umum, alatnya keren, semuanya fleksibel, tetapi Anda harus berhati-hati.

Itu saja, terima kasih sudah menonton!

All Articles