Komponen Arsitektur Android: Lifecycle dan LiveModel
() translation by (you can also view the original English article)
Di bagian terakhir dari seri ini, Pengantar Komponen Arsitektur Android kita berbicara tentang Arsitektur Android baru dan mengapa hal itu dikembangkan. Pada dasarnya, arsitektur baru ini membahas beberapa masalah Android yang diketahui dengan menawarkan seikat komponen yang dibuat khusus untuk sistem ini. Ini adalah blok bangunan dari arsitektur. Kami sudah melihat komponen ini, jadi sekarang saatnya untuk mulai memahami lebih dalam akan mereka.
Dalam tutorial ini, kita akan melihat dari dekat komponen Lifecycle
dan the LiveModel
. Saat kami mengeksplorasi ini, kami juga akan memeriksa beberapa cuplikan kode dari contoh aplikasi Karena kita berbicara tentang paradigma baru Android, cuplikan semuanya dibuat dengan Kotlin yang mengagumkan .
Jika anda belum kenal Kotlin, tolong jangan takut untuk mengikuti; Implementasinya sangat dekat dengan Java, dan saya yakin anda bisa memahaminya. Jika anda ingin belajar lebih banyak tentang Kotlin, Jessica Thornsby menulis sebuah rangkaian yang sangat bagus di sini pada Tuts + mengenai Coding Aplikasi Android di Kotlin . Anda harus melihatnya!
Mengkodekan Aplikasi Android Fungsional di Kotlin: Persiapan
Mengkodekan Aplikasi Android Fungsional di Kotlin: Lambdas, Null Safety & More
Contoh Proyek
Kami menyediakan aplikasi kecil yang mendemonstrasikan konsep yang sedang kita bicarakan dalam tutorial ini. Nama aplikasi itu adalah MyWeatherApp, dan ia memungkinkan pengguna untuk mengetahui cuaca hari itu menggunakan nama kota atau lokasi pengguna saat ini. Logika aplikasi cukup sederhana, namun anda dapat memperbaikinya untuk membuat aplikasi anda sendiri.



Seperti yang dapat anda lihat pada diagram di bawah ini, arsitekturnya sesuai dengan yang diusulkan oleh Android, dan kami menggunakan paket Komponen Arsitektur baru sebanyak mungkin, menjaga hal-hal menjadi cukup sederhana untuk analisis dasar. Sebagai bonus, kami menggunakan Dagger 2 sebagai perpustakaan Injeksi Depedency. Namun, kami tidak akan menggali banyak detail tentang implementasinya, karena itu akan lepas dari cakupan tutorial.



Bagaimana App bekerja?
Aplikasinya diibuat sesederhana mungkin. Ia hanya memiliki satu Kegiatan, tempat pengguna bisa mendapatkan cuaca dengan mencari nama kota atau menggunakan lokasi perangkat saat ini. MainActivity
memanggil MainModel
untuk mendapatkan LiveData
yang tampak dan bereaksi terhadapnya. MainModel
mengambil data cuaca dari MainRepository
, dan mengkonsolidasikan semua data sebagai LiveData
. MainRepository
mendapatkan datanya dari berbagai sumber.
Menjalankan Aplikasi Sampel
Download atau kloning repositori dari repo GitHubc kami dan bangun dengan Gradle atau membukanya di IDE Anda. Anda juga harus membuat akun OpenWeatherMap dan dapatkan ID aplikasi baru. Tambahkan ID aplikasi pada sumber daya string yang disebut openWeather
.
1 |
<string name="openWeather">XXXXXXXXXXXXXXX</string> |
2. Menyiapkan Proyek
Karena Komponen Arsitektur masih dalam alfa, anda harus menyertakan repositori Google, yang berisi beberapa perpustakaan eksperimental, dalam proyek build.gradle
.
1 |
allprojects { |
2 |
repositories { |
3 |
|
4 |
// add this repository |
5 |
maven { url 'https://maven.google.com' } |
6 |
} |
7 |
} |
Dalam modul build.gradle, tambahkan hal berikut ke bagian dependencies
guna menambahkan dukungan untuk Lifecycles
, LiveData
, dan ViewModel
:
compile "android.arch.lifecycle:runtime:1.0.0-alpha5"
compile "android.arch.lifecycle:extensions:1.0.0-alpha5"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha5"
Jika anda menggunakan Kotlin, anda juga harus menambahkan atau mengganti annotationProcessor
dengan Kapt
,yang menangani anotasi pada Kotlin.
1 |
kapt "android.arch.lifecycle:compiler:1.0.0-alpha5" |
Untuk mengaktifkan Kapt
,tambahkan kode berikut dalam modul build.gradle
root.
1 |
kapt { |
2 |
generateStubs = true |
3 |
} |
3. Komponen Lifecycle
Setiap pengembang Android terbiasa dengan konsep lifecycle. Sistem ini mendorong lifecycle Aplikasi, Aktivitas, Fragmen, dan sebagainya, tanpa kendali pengembang. Konsep ini adalah salah satu paradigma Android dan, sampai saat ini, tidak mudah bekerja dengannya, karena tidak mungkin langsung memeriksa status lifecycle komponen. Yang bisa kita lakukan adalah bereaksi terhadap metode tertentu, seperti onCreate
dan onDestroy
, dipicu oleh lifecycle events.



Ini semua telah berubah sejak pengumuman Paket komponen Arsitektur, yang mengenalkan komponen yang disebut Lifecycle
. Sekarang, beberapa objek Android memiliki Lifecycle
yang melekat pada mereka, dan ini mengubah banyak hal bagi para pengembang. Mungkin untuk berkonsultasi dengan Lifecycle
state pada waktu tertentu, dan juga mungkin untuk bereaksi terhadap Lifecycle
events menggunakan anotasi. Padahal, tulang punggung Komponen Arsitektur Android yang baru adalah komponen Lifecycle
.
Semua elemen dari paket android.arch.lifecycle
penting untuk konsep lifecycle, tapi dua di antaranya patut mendapat perhatian lebih: LifecycleOwner
dan LifecycleObserver
. Mereka menciptakan kemungkinan bekerja dengan Lifecycle
, mengamati serta bereaksi terhadap kejadian yang terjadi pada Kegiatan, Fragmen, Layanan dan sebagainya.
LifecycleOwner
LifecycleOwner
adalah metode interface tunggal untuk kelas yang berisi Lifecycle
. Ia mengintisarikan kepemilikan Lifecycle
, yang memungkinkan anda untuk menulis komponen yang bisa bekerja dengannya. Dengan standar baru, Aktivitas dan Fragmen merupakan LifecycleOwner
.Namun, sampai versi terakhir dari Komponen Arsitektur diluncurkan,anda harus menggunakan beberapa kelas khusus: ActivityLifecycle
, FragmentLifecycle
, dan LifecycleService
.
1 |
class MainActivity : LifecycleActivity() { |
2 |
override fun onCreate(savedInstanceState: Bundle?) { |
3 |
super.onCreate(savedInstanceState) |
4 |
} |
5 |
} |
Tidak ada perubahan signifikan dalam pelaksanaan kelas ini jika dibandingkan dengan Aktivitas dan Fragmen standar. Begitu kelas memanjang, mereka akan memiliki Lifecycle
terlampir, yang bisa diambil kapan saja dengan metode getLifecycle ()
. Kemungkinan lain yang menarik adalah kita bisa mengecek keadaan ifecycle saat ini dengan getCurrentState
,yang mengembalikan Lifecycle.State
.
Ada lima keadaan Lifecycle
yang berbeda:
-
Diinisialisasi
: untuk sebuah objek yang telah disebut, tapi yang belum "aktif". Ini setara dengan keadaan sebelum metodeActivity.onCreate
. -
DIBUAT
: untuk objek yang baru saja dibuat. Hal ini disebut setelah metodeonCreate
dan juga disebut tepat sebelum metodeonStop
.
-
MEMULAI
: disebut setelahonStart
dan tepat sebelum metodeonPause
.
-
Dilanjutkan
: Keadaan aktif atau melanjutkan keadaan untukLifecycleOwner
. Dipanggil setelah metodeonResume
.
-
DIHANCURKAN
: untuk obyekLifecycleOwner
yang hancur.Lifecycle
ini tidak akan mengirimkan lebih banyak event. event ini tercapai tepat sebelum metodeonDestroy
.



LifecycleObserver
Salah satu sifat yang paling menarik dari Lifecycle
adalah ia dapat dengan mudah diamati. Kelas LifecycleObserver
dapat mengamati komponen LifecycleOwner
, seperti Aktivitas dan Fragmen. Ia menerima LifecycleOwner.EventS
dan dapat bereaksi terhadap mereka melalui anotasi @OnLifeCycleEvent(Lifecycle.Event)
.
1 |
class MainObserver : LifecycleObserver, AnkoLogger { |
2 |
@OnLifecycleEvent( Lifecycle.Event.ON_RESUME ) |
3 |
fun onResult() { |
4 |
info("onResult") |
5 |
} |
6 |
@OnLifecycleEvent( Lifecycle.Event.ON_STOP ) |
7 |
fun onStop() { |
8 |
info("onStop") |
9 |
} |
10 |
} |
Metode yang dijelaskan dengan @OnLifecycleEvent
tidak memerlukan argumen, tapi jika digunakan, argumen pertama pasti LifecycleOwner
. Ketika anotasi menggunakan Lifecycle.Event.ON_ANY
, metode harus mengharapkan dua argumen: LifecycleOwner
dan Lifecycle.Event
.
1 |
@OnLifecycleEvent( Lifecycle.Event.ON_ANY ) |
2 |
fun onEvent( owner: LifecycleOwner, event: Lifecycle.Event ) |
3 |
{ |
4 |
info("onEvent: ownerState: ${owner.lifecycle.currentState}") |
5 |
info("onEvent: event: $event") |
6 |
} |
Untuk mengaktifkan anotasi @OnLifecycleEvent
, LifecycleObserver
harus memperhatikan Lifecycle
, jika tidak maka ia tidak akan menerima events. Untuk membuatny berfungsi, hubungi Lifecycle.addObserver(LifecycleOwner)
dan LifecycleOwner
selanjutnya akan mampu bereaksi terhadap Lifecycle.Event
. Hal ini juga memungkinkan untuk memanggil Lifecycle.removeObsever(LifecycleObserver)
untuk menghapus pengamat
1 |
class MainActivity : LifecycleActivity(), AnkoLogger { |
2 |
@Inject lateinit var mainObserver: MainObserver |
3 |
|
4 |
override fun onCreate(savedInstanceState: Bundle?) { |
5 |
// ... |
6 |
// On Kotlin, instead of getLifecycle, |
7 |
// we can call lifecycle directly |
8 |
lifecycle.addObserver( mainObserver ) |
9 |
} |
10 |
|
11 |
override fun onDestroy() { |
12 |
// ... |
13 |
lifecycle.removeObserver( mainObserver ) |
14 |
} |
15 |
} |
Ada berbagai kasus penggunaan yang menarik untuk LifecycleObserver
. Misalnya, ia bisa digunakan untuk membuat layer Presenter dari pola arsitektur Model View Presenter
. Bisa juga digunakan untuk menciptakan pendengar yang bisa berhenti mendengarkan saat Lifecycle dinonaktifkan Bisa juga digunakan untuk menciptakan pendengar yang bisa berhenti mendengarkan saat Lifecycle
dinonaktifkan
4. Komponen LiveModel
Dirancang untuk bekerja sama dengan lapisan UI, komponen ViewModel
menutup celah yang sudah ada di Android sejak awal: memberikan cara elegan untuk mengelola dan menyimpan data objek yang berhubungan dengan tampilan. Komponennya menjaga integritas data antara perubahan konfigurasi, dapat dibagi di antara Aktivitas dan Fragmen, dan merupakan alat yang sangat baik untuk menghindari kebocoran memori.
ViewModel
selalu diciptakan dalam hubungan yang dekat ke lingkup tertentu, baik Aktivitas atau Fragmen. Ruang lingkup dipertahankan selama Aktivitas atau Fragmen masih hidup. Secara praktis, ViewModel
terhubung kembali dengan tampilan setelah perubahan konfigurasi, mempertahankan diri sampai tampilan utama dihancurkan. Menurut dokumentasi resmi:
Tujuan dari ViewModel
adalah untuk memperoleh dan menyimpan informasi yang diperlukan untuk suatu Kegiatan atau Fragmen.



Di atas semua itu, ViewModel
memfasilitasi pemisahan keprihatinan dalam proses pengembangan Android. Dengan memindahkan semua operasi yang berkaitan dengan data ke komponen ini dan dengan membiarkannya menangani logika, aplikasi testability dan maintainability menjadi sangat meningkat. Dengan ViewModel
, itu mungkin untuk dengan mudah mengadopsi Arsitektur Android yang diusulkan pada Google I/O 2017. Anda bahkan bisa menggunakannya untuk mengadopsi pola arsitektur yang lebih canggih, seperti MVP atau MVVM.
Menerapkan ViewModel
Ada dua cara untuk menerapkan ViewModel
. Yang standar adalah memperpanjang kelas, memberikan konstruktor tanpa argumen. Ini adalah cara termudah, tapi tidak bekerja dengan baik dengan Dependency Injection.
1 |
class MainViewModel : ViewModel() { |
2 |
init { |
3 |
// initialize some behavior |
4 |
} |
5 |
|
6 |
fun getData() : LiveData<String> { |
7 |
// get some data |
8 |
} |
9 |
|
10 |
override fun onCleared() { |
11 |
super.onCleared() |
12 |
// called before its destruction |
13 |
} |
14 |
} |
Untuk mendapatkan ViewModel
yang dibangun dengan teknik ini dari Aktivitas atau Fragmen, cukup panggil ViewModelProviders.of(FragmentActivity).get(Class<T>). Argumen terakhir harus berisi kelas ViewModel. Instance ViewModel yang sama akan diambil oleh tampilan dan akan berisi semua data untuk tampilan itu. Argumen terakhir harus berisi kelas ViewModel
. Instance ViewModel
yang sama akan diambil oleh tampilan dan akan berisi semua data untuk tampilan itu.
1 |
val viewModel: MainViewModel = |
2 |
ViewModelProviders.of(this).get(MyViewModel::class.java) |
Perhatikan bahwa, sejak ViewModel
diambil dari metode ViewModelProviders.of
, konstruktornya tidak dapat menerima argumen. Sebagai solusi, anda bisa menerapkan View ViewModelProvider.Factory
. Sebenarnya ini adalah teknik yang sama yang kita gunakan untuk memasukan ViewModel
.
Memasukkan ViewModel
Saat menggunakan DI, keadaan menjadi sedikit lebih rumit. Anda harus menerapkannya ViewModelProvider.Factory
. Langkah-langkah berikut bisa digunakan untuk memasukkan ViewModel
dengan menggunakan Dagger. ViewModelFactory
adalah kelas utilitas yang menyediakan ViewModel
untuk sebuah lingkup
1 |
@Suppress("UNCHECKED_CAST") |
2 |
@Singleton |
3 |
class ViewModelFactory |
4 |
@Inject |
5 |
constructor( |
6 |
private val creators: Map<Class<out ViewModel>, |
7 |
@JvmSuppressWildcards Provider<ViewModel>> |
8 |
) : ViewModelProvider.Factory { |
9 |
|
10 |
override fun <T : ViewModel> create(modelClass: Class<T>): T { |
11 |
var creator: Provider<out ViewModel>? = creators[modelClass] |
12 |
if (creator == null) { |
13 |
for ((key, value) in creators) { |
14 |
if (modelClass.isAssignableFrom(key)) { |
15 |
creator = value |
16 |
break |
17 |
} |
18 |
} |
19 |
} |
20 |
if (creator == null) { |
21 |
throw IllegalArgumentException("unknown model class " + modelClass) |
22 |
} |
23 |
try { |
24 |
return creator.get() as T |
25 |
} catch (e: Exception) { |
26 |
throw RuntimeException(e) |
27 |
} |
28 |
|
29 |
} |
30 |
} |
Bagger juga butuh @MapKey
didefinisikan untuk ViewModel
dan pengikat untuk setiap model dan untuk pabrik di modulnya
1 |
// @MapKey |
2 |
@MustBeDocumented |
3 |
@Target( |
4 |
AnnotationTarget.FUNCTION, |
5 |
AnnotationTarget.PROPERTY_GETTER, |
6 |
AnnotationTarget.PROPERTY_SETTER |
7 |
) |
8 |
@kotlin.annotation.Retention() |
9 |
@MapKey |
10 |
internal annotation class ViewModelKey( |
11 |
val value: KClass<out ViewModel>) |
12 |
|
13 |
// ViewModel Module |
14 |
@Module |
15 |
abstract class ViewModelsModule { |
16 |
// Bind each ViewModel |
17 |
@Binds |
18 |
@IntoMap |
19 |
@ViewModelKey( MainViewModel::class ) |
20 |
abstract fun bindMainViewModel( mainViewModel: MainViewModel ) : ViewModel |
21 |
|
22 |
// ViewModel factory binding |
23 |
@Binds |
24 |
abstract fun bindViewModelFactory( factory: ViewModelFactory ) : ViewModelProvider.Factory |
25 |
} |
Setelah itu ikuti prosedur Dagger standar dan anda akan bisa membuat ViewModel
yang mampu memasukan argumen pada konstruktornya. Untuk membuat instance baru, dapatkan ViewModelFactory
dan ambil ViewModel
yang diinginkan darinya.
1 |
// Get the ViewModel factory |
2 |
@Inject lateinit var viewModelFactory: |
3 |
ViewModelProvider.Factory |
4 |
|
5 |
// Get ViewModel |
6 |
val viewModel = ViewModelProviders.of(this, viewModelFactory) |
7 |
.get(MainViewModel::class.java) |
Dalam proyek sampel kami, anda dapat melihat dari dekat DI menggunakan Dagger. saya juga sudah memberikan Folder contoh di tutorial GitHub repo dengan cuplikan yang menunjukkan cara mengkonfigurasi ViewModels
pada sistem Dagger menggunakan Kotlin.
1 |
class MainViewModel |
2 |
@Inject |
3 |
constructor( |
4 |
private val repository: MainRepository |
5 |
) |
6 |
: ViewModel(), AnkoLogger { |
7 |
|
8 |
// ... code goes here |
9 |
} |
Kesimpulan
Sejauh ini, perjalanan kita melalui Komponen Arsitektur Android baru sudah sangat produktif. Namun, kita masih punya banyak hal untuk di bahas. Pada tutorial selanjutnya, kita akan membicarakan komponen LiveData
yang mengagumkan, menyelidiki fitur dasar dan lanjutannya, dan menerapkan konsep ini ke aplikasi sampel kita.
Sampai jumpa lagi! Dan sementara itu, lihat beberapa postingan kami yang lain mengenai pengembangan aplikasi Android!