Journal Entry
Mengatasi UI State yang hilang akibat Process Death di Android | by Anaf Naufalian
Mengatasi UI State yang hilang akibat Process Death di Android | by Anaf Naufalian
Sep 15, 2023
Process Death, siapa si yang nggak kesel sama masalah ini?, misalnya kita lagi buka aplikasi chatting dan kita udah ketik pesan panjang lebar, pas kita pindah ke aplikasi lain, misalnya ke aplikasi edit video, dan kita mengedit video di aplikasi tersebut, setelah selesai mengedit video kita pindah ke aplikasi chatting tadi, eh tiba-tiba pesan yang kita ketik panjang lebar tadi hilang, nahhh bisa jadi itu karena process death.
Oke, apa itu process death?, Process Death atau yang biasa disebut System-initiated process death adalah kejadian yang terjadi karena sistem Android menghentikan suatu proses dari aplikasi yang sedang berjalan di background (latar belakang) untuk membebaskan sumber daya/RAM yang nantinya akan dipakai oleh aplikasi yang sedang berjalan di foreground (latar depan).
Perbedaan User-initiated process death dan System-initiated process death adalah User-initiated process death prosesnya di kill oleh user, seperti saat mengklik home button. System-initiated process death prosesnya di kill oleh sistem, contohnya seperti perubahan konfigurasi
Seperti contoh diatas, saat kita membuka aplikasi chatting dan kita mengetik pesan di EditText/TextField, biasanya pesan atau state dari EditText/TextField tersebut disimpan di dalam memori (RAM), ketika kita berpindah dari aplikasi chatting ke aplikasi edit video, maka aplikasi chatting beralih ke mode background dan aplikasi edit video beralih ke mode foreground. Saat kita mengedit video pastinya kita membutuhkan lebih banyak sumber daya, ketika sumber daya tidak cukup disinilah sistem Android akan mematikan/kill aplikasi-aplikasi yang berjalan di background, tetapi sebelum sistem Android mematikan aplikasi yang berjalan di background, sistem akan memanggil fungsi onSavedInstanceState() untuk menyimpan state yang kita berikan, setelah fungsi tersebut dipanggil barulah sistem akan mematikan aplikasi tersebut. Nah, setelah edit video tadi kan kita buka lagi aplikasi chatting, tapi kenapa teks yang sudah kita ketik tadi bisa hilang?, itu mungkin karena developer dari aplikasi tersebut tidak mengimplementasikan onSavedInstanceState() untuk menyimpan state.
Ada beberapa cara untuk menyimpan state di android, yaitu:
- Jetpack Compose: bisa memakai rememberSaveable
- View: bisa menggunakan fungsi onSavedInstanceState() di activity
- ViewModel: bisa menggunakan SavedStateHandle
Untuk kasus ini saya akan mengimplementasikannya di ViewModel dan menggunakan library hilt untuk dependency injection-nya, oke langsung saja pertama kita buat kelas BaseViewModel, untuk apa class BaseViewModel? kelas ini nantinya akan digunakan sebagai parent class dari view model yang akan kita buat, kelas ini juga akan mewarisi (extends) kelas ViewModel.
BaseViewModel.kt
/**
* kelas dasar (base class) untuk view model.
* Ini berarti kelas ini memberikan kerangka dasar untuk view model
* yang akan diturunkan (derived) oleh kelas-kelas lain.
*
* @param savedStateHandle savedStateHandle yang digunakan untuk menyimpan state
* @param defaultState default state
*
* @author kafri8889
*/
abstract class BaseViewModel<STATE: Parcelable>(
private val savedStateHandle: SavedStateHandle,
private val defaultState: STATE
): ViewModel() {
// Key yang digunakan untuk menyimpan dan mengambil state di savedStateHandle
private val KEY_STATE = "state"
val state: StateFlow<STATE> = savedStateHandle.getStateFlow(KEY_STATE, defaultState)
/**
* Function yang digunakan untuk memperbarui state dari [savedStateHandle]
*
* @param newState parameter ini akan memberikan state saat ini sebagai `this`.
*/
protected fun updateState(newState: STATE.() -> STATE) {
// get current state
savedStateHandle.get<STATE>(KEY_STATE)?.let { state ->
// simpan state baru ke savedStateHandle
savedStateHandle[KEY_STATE] = newState(state)
}
}
}
Dari kode diatas BaseViewModel membutuhkan 2 parameter yaitu savedStateHandle dan defaultState.
Kata kunci “STATE” dari kode diatas adalah sebuah generic type yang menggambarkan tipe data dari state yang akan digunakan didalam kelas BaseViewModel, “STATE” yang diberikan juga harus mewarisi kelas Parcelable, kenapa harus menggunakan Parcelable?, karena state yang kita berikan adalah kustom data class, dan savedStateHandle menggunakan Bundle untuk menyimpan state yang diberikan, jika kita tidak mengimplementasikan Parcelable ke state yang kita punya dan kita tetap memaksa untuk menyimpan state ke dalam savedStateHandle, maka akan terjadi error.
Selanjutnya kita membuat kelas MyState yang digunakan sebagai tipe data state dalam kelas BaseViewModel.
MyState.kt
@Parcelize
data class MyState(
val text: String = ""
): Parcelable
Setelah itu kita akan membuat kelas _MyViewModel (_kelas ini harus mewarisi kelas BaseViewModel).
MyViewModel.kt
@HiltViewModel
class MyViewModel @Inject constructor(
savedStateHandle: SavedStateHandle
): BaseViewModel<MyState>(
savedStateHandle = savedStateHandle,
defaultState = MyState()
) {
/**
* Funtion yang digunakan untuk memperbarui teks dari text field ke [savedStateHandle]
*/
fun updateText(newText: String) {
updateState {
copy(
text = newText
)
}
}
}
Selanjutnya kita akan membuat UI yang akan ditampilkan ke pengguna
MyScreen.kt
@Composable
fun MyScreen(
viewModel: MyViewModel = hiltViewModel()
) {
// Observe state
val state by viewModel.state.collectAsStateWithLifecycle()
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
) {
OutlinedTextField(
value = state.text,
onValueChange = viewModel::updateText
)
}
}
Lalu di MainActivity.
MainActivity.kt
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeResearchTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
MyScreen()
}
}
}
}
}
Jika semuanya sudah selesai, saat kita menjalankan aplikasi harusnya muncul tampilan seperti dibawah

Untuk mensimulasikan System-initiated process death ikuti cara dibawah:
- Pertama: Run aplikasi di android studio.

- Kedua: Minimize aplikasi dengan cara menekan tombol “home”.
[other]Minimize aplikasi[/other]
- Ketiga: Buka “Device Explorer” di android studio dan pindah ke tab “Processes”, disini kita akan melihat package name aplikasi kita jika aplikasi berjalan.

- Keempat: Pilih aplikasi kalian dan tekan tombol “Kill process”.
[other]Kill app from device exploler[/other]
- Kelima: Buka kembali aplikasi, jika saat membuka aplikasi muncul splash screen atau blank itu tandanya aplikasi sudah di kill sebelumnya, dan jika sebelumnya kalian mengetik teks ke dalam text field sebelum aplikasi di minimize, maka setelah kalian kill aplikasi tadi dan kalian kembali ke aplikasi, seharusnya text yang kalian ketik tadi masih ada.
[other]Preview[/other]
Jika saat kalian mencoba dan hasilnya seperti video diatas maka implementasinya sudah benar, untuk source kodenya bisa klik link dibawah.
[Github-kafri8889/Compose-Research:Processdeath
Contribute to kafri8889/Compose-Research development by creating an account on GitHub.
Contoh penggunaanya bisa kalian lihat di projek ini
[GitHub - kafri8889/DailyCost: Aplikasi pengelola keuangan
Aplikasi pengelola keuangan. Contribute to kafri8889/DailyCost development by creating an account on GitHub.
github.com](https://github.com/kafri8889/DailyCost?source=post_page-----d4b0b6c026da---------------------------------------)
terima kasih sudah membaca artikel ini.
Referensi