Menangani perubahan konfigurasi

Sebagian konfigurasi perangkat bisa berubah saat runtime (misalnya orientasi layar, ketersediaan keyboard, dan saat pengguna mengaktifkan mode multi-jendela). Saat perubahan demikian terjadi, Android akan memulai ulang Activity yang berjalan (onDestroy() dipanggil, diikuti oleh onCreate()). Perilaku mulai ulang didesain untuk membantu aplikasi Anda beradaptasi dengan konfigurasi baru melalui pemuatan ulang aplikasi Anda secara otomatis dengan sumber daya alternatif yang sesuai dengan konfigurasi perangkat baru.

Untuk menangani secara tepat mulai ulang, penting bahwa aktivitas Anda memulihkan status sebelumnya. Anda bisa menggunakan kombinasi objek onSaveInstanceState(), ViewModel, dan penyimpanan persisten untuk menyimpan dan memulihkan status UI aktivitas Anda di seluruh perubahan UI. Untuk informasi selengkapnya tentang cara menyimpan status Aktivitas Anda, baca Menyimpan Status UI.

Untuk menguji bahwa aplikasi memulai ulang sendiri dengan status tak berubah, Anda harus memanggil perubahan konfigurasi (seperti mengubah orientasi layar) saat melakukan berbagai tugas dalam aplikasi. Aplikasi Anda harus dapat memulai ulang setiap saat tanpa kehilangan data pengguna atau status untuk menangani kejadian seperti perubahan konfigurasi atau bila pengguna menerima panggilan telepon masuk lalu kembali ke aplikasi setelah proses aplikasi Anda dimusnahkan. Untuk mengetahui cara mengembalikan status aktivitas, bacalah tentang Daur hidup aktivitas.

Akan tetapi, Anda mungkin menemui situasi ketika memulai ulang aplikasi dan memulihkan data dalam jumlah besar bisa menjadi mahal dan menghasilkan pengalaman pengguna yang buruk. Dalam situasi demikian, Anda memiliki dua opsi lain:

  1. Mempertahankan objek selama perubahan konfigurasi

    Izinkan aktivitas Anda memulai ulang saat konfigurasi berubah, namun bawa objek berstatus ke instance baru aktivitas Anda.

  2. Menangani sendiri perubahan konfigurasi

    Tidak disarankan menangani sendiri perubahan konfigurasi karena kompleksitas tersembunyi dalam menangani perubahan konfigurasi. Namun, jika tidak dapat mempertahankan status UI menggunakan opsi yang lebih disukai (onSaveInstanceState(), ViewModels, dan penyimpanan persistent) Anda dapat mencegah sistem memulai kembali ulang aktivitas selama perubahan konfigurasi tertentu. Aplikasi Anda akan menerima callback ketika konfigurasi melakukan perubahan, sehingga jika diperlukan, Anda dapat memperbarui aktivitas secara manual.

Mempertahankan objek selama perubahan konfigurasi

Jika memulai ulang aktivitas mengharuskan pemulihan serangkaian data dalam jumlah besar, menghubungkan kembali koneksi jaringan, atau melakukan operasi intensif lainnya, maka mulai ulang penuh karena perubahan konfigurasi mungkin menjadi pengalaman pengguna yang lambat. Selain itu, Anda mungkin tidak bisa sepenuhnya memulihkan status aktivitas dengan Bundle yang disimpan sistem untuk Anda dengan callback onSaveInstanceState()—hal ini tidak didesain untuk membawa objek besar (seperti bitmap) dan data di dalamnya harus diserialkan kemudian dinonserialkan di thread utama, yang bisa menghabiskan banyak memori dan membuat perubahan konfigurasi menjadi lambat. Dalam situasi demikian, Anda dapat mengurangi beban menginisialisasi ulang bagian dari aktivitas Anda menggunakan objek ViewModel. ViewModels dipertahankan di perubahan konfigurasi, sehingga ini merupakan tempat yang bagus untuk menyimpan data UI tanpa harus menanyakannya lagi. Untuk informasi selengkapnya tentang menggunakan ViewModels di aplikasi, baca panduan ViewModel.

Menangani sendiri perubahan konfigurasi

Jika aplikasi Anda tidak memerlukan pembaruan sumber daya selama perubahan konfigurasi tertentu dan Anda memiliki keterbatasan kinerja yang mengharuskan Anda untuk menghindari mulai ulang aktivitas, maka Anda bisa mendeklarasikan agar aktivitas Anda menangani sendiri perubahan konfigurasinya, sehingga mencegah sistem memulai ulang aktivitas.

Perhatian: Menangani sendiri perubahan konfigurasi bisa jauh lebih mempersulit penggunaan sumber daya alternatif, karena sistem tidak menerapkannya secara otomatis untuk Anda. Teknik ini harus dianggap sebagai usaha terakhir bila Anda harus menghindari mulai ulang karena perubahan konfigurasi dan tidak disarankan untuk sebagian besar aplikasi.

Untuk mendeklarasikan agar aktivitas Anda menangani perubahan konfigurasi, edit elemen <activity> yang sesuai dalam file manifes agar menyertakan atribut android:configChanges dengan nilai yang mewakili konfigurasi yang ingin ditangani. Nilai yang memungkinkan dicantumkan dalam dokumentasi untuk atribut android:configChanges. Nilai yang paling umum digunakan "orientation", "screenSize", dan "keyboardHidden". Nilai "orientation" mencegah memulai ulang saat orientasi layar berubah. Nilai "screenSize" juga mencegah memulai ulang saat orientasi berubah, tetapi diawali di Android 3.2 (API level 13). Jika ingin menangani perubahan konfigurasi secara manual di aplikasi, Anda harus mendeklarasikan nilai "orientation" dan "screenSize" di atribut android:configChanges. Nilai "keyboardHidden" mencegah memulai ulang saat ketersediaan keyboard berubah. Anda bisa mendeklarasikan beberapa nilai konfigurasi dalam atribut dengan memisahkannya menggunakan karakter pipa |.

Misalnya, kode manifes berikut menyatakan aktivitas yang menangani perubahan orientasi layar maupun perubahan ketersediaan keyboard:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

Sekarang, jika salah satu konfigurasi ini berubah, MyActivity tidak akan dimulai ulang. Sebagai gantinya, MyActivity menerima panggilan ke onConfigurationChanged(). Metode ini meneruskan objek Configuration yang menetapkan konfigurasi perangkat baru. Dengan membaca kolom dalam Configuration, Anda dapat menentukan konfigurasi baru dan membuat perubahan yang sesuai dengan memperbarui sumber daya yang digunakan dalam antarmuka. Pada saat metode ini dipanggil, objek Resources aktivitas Anda akan diperbarui untuk mengembalikan sumber daya berdasarkan konfigurasi baru, jadi Anda bisa dengan mudah menyetel ulang elemen UI tanpa membuat sistem memulai ulang aktivitas Anda.

Misalnya, implementasi onConfigurationChanged() berikut akan memeriksa orientasi perangkat saat ini:

Kotlin

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    // Checks the orientation of the screen
    if (newConfig.orientation === Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show()
    } else if (newConfig.orientation === Configuration.ORIENTATION_PORTRAIT) {
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show()
    }
}

Java

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

Objek Configuration mewakili semua konfigurasi saat ini, tidak hanya konfigurasi yang telah berubah. Sering kali Anda tidak perlu memperhatikan dengan persis bagaimana konfigurasi berubah dan cukup menetapkan kembali semua sumber daya yang memberikan alternatif untuk konfigurasi sedang ditangani. Misalnya, karena objek Resources sekarang diperbarui, Anda dapat menyetel ulang ImageView dengan setImageResource() dan sumber daya yang sesuai untuk konfigurasi baru yang digunakan (seperti yang dijelaskan dalam Menyediakan Sumber Daya).

Perhatikan bahwa nilai-nilai dari kolom Configuration adalah integer yang sesuai dengan konstanta spesifik dari kelas Configuration. Untuk dokumentasi tentang konstanta yang harus digunakan di setiap kolom, lihat kolom yang sesuai dalam referensi Configuration.

Ingatlah: Saat mendeklarasikan aktivitas untuk menangani perubahan konfigurasi, Anda bertanggung jawab untuk menyetel ulang setiap elemen yang alternatifnya Anda berikan. Jika Anda mendeklarasikan aktivitas untuk menangani perubahan orientasi dan memiliki gambar yang harus berubah antara lanskap dan potret, Anda harus menetapkan kembali setiap sumber daya elemen selama onConfigurationChanged().

Jika Anda tidak perlu memperbarui aplikasi berdasarkan perubahan konfigurasi ini, sebagai gantinya Anda bisa saja tidak mengimplementasikan onConfigurationChanged(). Dalam hal ini, semua sumber daya yang digunakan sebelum perubahan konfigurasi akan tetap digunakan dan Anda hanya menghindari mulai ulang aktivitas. Akan tetapi, aplikasi Anda harus selalu bisa dimatikan dan dimulai ulang dengan status sebelumnya tetap utuh, sehingga Anda jangan menganggap teknik ini sebagai jalan keluar untuk mempertahankan status selama daur hidup aktivitas normal. Tidak hanya karena ada perubahan konfigurasi lainnya yang tidak bisa Anda cegah untuk memulai ulang aplikasi, namun juga karena Anda harus menangani kejadian seperti saat pengguna meninggalkan aplikasi dan dimusnahkan sebelum pengguna kembali ke aplikasi.