1 page.title=Menangani Perubahan Runtime 2 page.tags=aktivitas,daur hidup 3 @jd:body 4 5 <div id="qv-wrapper"> 6 <div id="qv"> 7 8 <h2>Dalam dokumen ini</h2> 9 <ol> 10 <li><a href="#RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</a></li> 11 <li><a href="#HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</a> 12 </ol> 13 14 <h2>Lihat juga</h2> 15 <ol> 16 <li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li> 17 <li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li> 18 <li><a href="http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html">Perubahan 19 Orientasi Layar yang Lebih Cepat</a></li> 20 </ol> 21 </div> 22 </div> 23 24 <p>Sebagian konfigurasi perangkat bisa berubah selama runtime 25 (seperti orientasi layar, ketersediaan keyboard, dan bahasa). Saat perubahan demikian terjadi, 26 Android akan me-restart 27 {@link android.app.Activity} yang berjalan ({@link android.app.Activity#onDestroy()} dipanggil, diikuti oleh {@link 28 android.app.Activity#onCreate(Bundle) onCreate()}). Perilaku restart didesain untuk membantu 29 aplikasi Anda beradaptasi dengan konfigurasi baru melalui pemuatan kembali aplikasi Anda secara otomatis dengan 30 sumber daya alternatif sumber yang sesuai dengan konfigurasi perangkat baru.</p> 31 32 <p>Untuk menangani restart dengan benar, aktivitas Anda harus mengembalikan 33 statusnya seperti semula melalui <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup 34 aktivitas</a> normal, dalam hal ini Android akan memanggil 35 {@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} sebelum menghentikan 36 aktivitas Anda sehingga Anda dapat menyimpan data mengenai status aplikasi. Selanjutnya Anda bisa mengembalikan status 37 selama {@link android.app.Activity#onCreate(Bundle) onCreate()} atau {@link 38 android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}.</p> 39 40 <p>Untuk menguji bahwa aplikasi me-restart sendiri dengan status tak berubah, Anda harus 41 memanggil perubahan konfigurasi (seperti mengubah orientasi layar) saat melakukan berbagai 42 tugas dalam aplikasi. Aplikasi Anda harus dapat me-restart setiap saat tanpa kehilangan 43 data pengguna atau status untuk menangani kejadian seperti perubahan konfigurasi atau bila pengguna menerima panggilan telepon 44 masuk lalu kembali ke aplikasi setelah proses 45 aplikasi Anda dimusnahkan. Untuk mengetahui cara mengembalikan status aktivitas, bacalah tentang <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup aktivitas</a>.</p> 46 47 <p>Akan tetapi, Anda mungkin menemui situasi ketika me-restart aplikasi dan 48 mengembalikan data dalam jumlah besar malah menjadi mahal dan menghasilkan pengalaman pengguna yang buruk. Dalam situasi 49 demikian, Anda memiliki dua opsi lain:</p> 50 51 <ol type="a"> 52 <li><a href="#RetainingAnObject">Mempertahankan objek selama perubahan konfigurasi</a> 53 <p>Izinkan aktivitas Anda me-restart saat konfigurasi berubah, namun bawa objek 54 berstatus (stateful) ke instance baru aktivitas Anda.</p> 55 56 </li> 57 <li><a href="#HandlingTheChange">Menangani sendiri perubahan konfigurasi</a> 58 <p>Cegah sistem me-restart aktivitas selama perubahan konfigurasi 59 tertentu, namun terima callback saat konfigurasi benar-benar berubah, agar Anda bisa memperbarui 60 aktivitas secara manual bila diperlukan.</p> 61 </li> 62 </ol> 63 64 65 <h2 id="RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</h2> 66 67 <p>Jika me-restart aktivitas mengharuskan pemulihan seperangkat data dalam jumlah besar, menghubungkan kembali koneksi 68 jaringan, atau melakukan operasi intensif lainnya, maka restart penuh karena perubahan konfigurasi mungkin 69 menjadi pengalaman pengguna yang lambat. Selain itu, Anda mungkin tidak bisa sepenuhnya mengembalikan status 70 aktivitas dengan {@link android.os.Bundle} yang disimpan sistem untuk Anda dengan callback {@link 71 android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()}—itu tidaklah 72 didesain untuk membawa objek besar (seperti bitmap) dan data di dalamnya harus diserialkan kemudian 73 dinon-serialkan, yang bisa menghabiskan banyak memori dan membuat perubahan konfigurasi menjadi lambat. Dalam situasi 74 demikian, Anda bisa meringankan beban memulai kembali aktivitas Anda dengan mempertahankan {@link 75 android.app.Fragment} saat aktivitas Anda di-restart karena perubahan konfigurasi. Fragmen ini 76 bisa berisi acuan ke objek stateful yang ingin Anda pertahankan.</p> 77 78 <p>Bila sistem Android menghentikan aktivitas Anda karena perubahan konfigurasi, fragmen 79 aktivitas yang telah ditandai untuk dipertahankan tidak akan dimusnahkan. Anda dapat menambahkan fragmen tersebut ke 80 aktivitas untuk mempertahankan objek stateful.</p> 81 82 <p>Untuk mempertahankan objek stateful dalam fragmen selama perubahan konfigurasi runtime:</p> 83 84 <ol> 85 <li>Perluas kelas {@link android.app.Fragment} dan deklarasikan referensi ke objek stateful 86 Anda.</li> 87 <li>Panggil {@link android.app.Fragment#setRetainInstance(boolean)} saat fragmen dibuat. 88 </li> 89 <li>Tambahkan fragmen ke aktivitas.</li> 90 <li>Gunakan {@link android.app.FragmentManager} untuk mengambil fragmen saat aktivitas 91 di-restart.</li> 92 </ol> 93 94 <p>Misalnya, definisikan fragmen sebagai berikut:</p> 95 96 <pre> 97 public class RetainedFragment extends Fragment { 98 99 // data object we want to retain 100 private MyDataObject data; 101 102 // this method is only called once for this fragment 103 @Override 104 public void onCreate(Bundle savedInstanceState) { 105 super.onCreate(savedInstanceState); 106 // retain this fragment 107 setRetainInstance(true); 108 } 109 110 public void setData(MyDataObject data) { 111 this.data = data; 112 } 113 114 public MyDataObject getData() { 115 return data; 116 } 117 } 118 </pre> 119 120 <p class="caution"><strong>Perhatian:</strong> Meskipun bisa menyimpan objek apa saja, Anda 121 sama sekali tidak boleh meneruskan objek yang terkait dengan {@link android.app.Activity}, seperti {@link 122 android.graphics.drawable.Drawable}, {@link android.widget.Adapter}, {@link android.view.View} 123 atau objek lainnya mana pun yang terkait dengan {@link android.content.Context}. Jika Anda melakukannya, hal tersebut akan 124 membocorkan semua tampilan dan sumber daya instance aktivitas semula. (Sumber daya yang bocor 125 berarti bahwa aplikasi Anda tetap menyimpannya dan tidak bisa dijadikan kumpulan sampah, sehingga bisa banyak 126 memori yang hilang.)</p> 127 128 <p>Selanjutnya gunakan {@link android.app.FragmentManager} untuk menambahkan fragmen ke aktivitas. 129 Anda bisa memperoleh objek data dari fragmen saat aktivitas memulai kembali selama perubahan 130 konfigurasi runtime. Misalnya, definisikan aktivitas Anda sebagai berikut:</p> 131 132 <pre> 133 public class MyActivity extends Activity { 134 135 private RetainedFragment dataFragment; 136 137 @Override 138 public void onCreate(Bundle savedInstanceState) { 139 super.onCreate(savedInstanceState); 140 setContentView(R.layout.main); 141 142 // find the retained fragment on activity restarts 143 FragmentManager fm = getFragmentManager(); 144 dataFragment = (DataFragment) fm.findFragmentByTag(data); 145 146 // create the fragment and data the first time 147 if (dataFragment == null) { 148 // add the fragment 149 dataFragment = new DataFragment(); 150 fm.beginTransaction().add(dataFragment, data).commit(); 151 // load the data from the web 152 dataFragment.setData(loadMyData()); 153 } 154 155 // the data is available in dataFragment.getData() 156 ... 157 } 158 159 @Override 160 public void onDestroy() { 161 super.onDestroy(); 162 // store the data in the fragment 163 dataFragment.setData(collectMyLoadedData()); 164 } 165 } 166 </pre> 167 168 <p>Dalam contoh ini, {@link android.app.Activity#onCreate(Bundle) onCreate()} menambahkan fragmen 169 atau mengembalikan referensinya. {@link android.app.Activity#onCreate(Bundle) onCreate()} juga 170 menyimpan objek stateful dalam instance fragmen. 171 {@link android.app.Activity#onDestroy() onDestroy()} akan memperbarui objek stateful dalam 172 instance fragmen yang dipertahankan.</p> 173 174 175 176 177 178 <h2 id="HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</h2> 179 180 <p>Jika aplikasi Anda tidak memerlukan pembaruan sumber daya selama perubahan konfigurasi 181 tertentu <em>dan</em> Anda memiliki keterbatasan kinerja yang mengharuskan Anda untuk 182 menghindari restart aktivitas, maka Anda bisa mendeklarasikan agar aktivitas Anda menangani sendiri perubahan 183 konfigurasinya, sehingga mencegah sistem me-restart aktivitas.</p> 184 185 <p class="note"><strong>Catatan:</strong> Menangani sendiri perubahan konfigurasi bisa jauh lebih 186 mempersulit penggunaan sumber daya alternatif, karena sistem tidak menerapkannya secara otomatis 187 untuk Anda. Teknik ini harus dianggap sebagai usaha terakhir bila Anda harus menghindari restart 188 karena perubahan konfigurasi dan tidak disarankan untuk sebagian besar aplikasi.</p> 189 190 <p>Untuk mendeklarasikan agar aktivitas Anda menangani perubahan konfigurasi, edit elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> yang sesuai 191 dalam file manifes Anda agar menyertakan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code 192 android:configChanges}</a> dengan nilai yang mewakili konfigurasi yang ingin 193 ditangani. Nilai yang memungkinkan tercantum dalam dokumentasi untuk atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code 194 android:configChanges}</a> (nilai paling sering digunakan adalah {@code "orientation"} untuk 195 mencegah restart saat orientasi layar berubah dan {@code "keyboardHidden"} untuk mencegah 196 restart saat ketersediaan keyboard berubah). Anda dapat mendeklarasikan beberapa nilai konfigurasi 197 dalam atribut dengan memisahkannya menggunakan karakter pipa {@code |}.</p> 198 199 <p>Misalnya, kode manifes berikut menyatakan aktivitas yang menangani 200 perubahan orientasi layar maupun perubahan ketersediaan keyboard:</p> 201 202 <pre> 203 <activity android:name=".MyActivity" 204 android:configChanges="orientation|keyboardHidden" 205 android:label="@string/app_name"> 206 </pre> 207 208 <p>Sekarang, bila salah satu konfigurasi ini berubah, {@code MyActivity} tidak akan me-restart. 209 Sebagai gantinya, {@code MyActivity} akan menerima panggilan ke {@link 210 android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Metode ini 211 meneruskan objek {@link android.content.res.Configuration} yang menetapkan 212 konfigurasi perangkat baru. Dengan membaca bidang-bidang dalam {@link android.content.res.Configuration}, 213 Anda dapat menentukan konfigurasi baru dan membuat perubahan yang sesuai dengan memperbarui 214 sumber daya yang digunakan dalam antarmuka. Pada saat 215 metode ini dipanggil, objek {@link android.content.res.Resources} aktivitas Anda akan diperbarui untuk 216 mengembalikan sumber daya berdasarkan konfigurasi baru, jadi Anda bisa dengan mudah 217 me-reset elemen UI tanpa membuat sistem me-restart aktivitas Anda.</p> 218 219 <p class="caution"><strong>Perhatian:</strong> Mulai Android 3.2 (API level 13), <strong> 220 "ukuran layar" juga berubah</strong> bila perangkat beralih orientasi antara potret 221 dan lanskap. Jadi jika Anda tidak ingin runtime di-restart karena perubahan orientasi saat mengembangkan 222 API level 13 atau yang lebih tinggi (sebagaimana dideklarasikan oleh atribut <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> dan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> 223 ), Anda harus menyertakan nilai {@code "screenSize"} selain nilai {@code 224 "orientation"}. Yaitu Anda harus mendeklarasikan {@code 225 android:configChanges="orientation|screenSize"}. Akan tetapi, jika aplikasi Anda menargetkan API level 226 12 atau yang lebih rendah, maka aktivitas Anda akan selalu menangani sendiri perubahan konfigurasi ini (perubahan 227 konfigurasi ini tidak me-restart aktivitas Anda, bahkan saat berjalan pada perangkat Android 3.2 atau yang lebih tinggi).</p> 228 229 <p>Misalnya, implementasi {@link 230 android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} berikut akan 231 memeriksa orientasi perangkat saat ini:</p> 232 233 <pre> 234 @Override 235 public void onConfigurationChanged(Configuration newConfig) { 236 super.onConfigurationChanged(newConfig); 237 238 // Checks the orientation of the screen 239 if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { 240 Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); 241 } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ 242 Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); 243 } 244 } 245 </pre> 246 247 <p>Objek {@link android.content.res.Configuration} mewakili semua konfigurasi 248 saat ini, tidak hanya konfigurasi yang telah berubah. Seringkali Anda tidak perlu memperhatikan dengan persis bagaimana 249 konfigurasi berubah dan cukup menetapkan kembali semua sumber daya yang memberikan alternatif untuk 250 konfigurasi sedang ditangani. Misalnya, karena objek {@link 251 android.content.res.Resources} sekarang diperbarui, Anda dapat me-reset 252 setiap {@link android.widget.ImageView} dengan {@link android.widget.ImageView#setImageResource(int) 253 setImageResource()} 254 dan sumber daya yang sesuai untuk konfigurasi baru yang digunakan (seperti dijelaskan dalam <a href="providing-resources.html#AlternateResources">Menyediakan Sumber Daya</a>).</p> 255 256 <p>Perhatikan bahwa nilai-nilai dari bidang {@link 257 android.content.res.Configuration} adalah integer yang sesuai dengan konstanta spesifik 258 dari kelas {@link android.content.res.Configuration}. Untuk dokumentasi tentang konstanta 259 yang harus digunakan di setiap bidang, lihat bidang yang sesuai dalam referensi {@link 260 android.content.res.Configuration}.</p> 261 262 <p class="note"><strong>Ingatlah:</strong> Saat mendeklarasikan aktivitas untuk menangani perubahan 263 konfigurasi, Anda bertanggung jawab untuk me-reset setiap elemen yang alternatifnya Anda berikan. Jika Anda 264 mendeklarasikan aktivitas untuk menangani perubahan orientasi dan memiliki gambar yang harus berubah 265 antara lanskap dan potret, Anda harus menetapkan kembali setiap sumber daya elemen selama {@link 266 android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}.</p> 267 268 <p>Jika Anda tidak perlu memperbarui aplikasi berdasarkan perubahan 269 konfigurasi ini, sebagai gantinya Anda bisa saja <em>tidak</em> mengimplementasikan {@link 270 android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Dalam 271 hal ini, semua sumber daya yang digunakan sebelum perubahan konfigurasi akan tetap digunakan 272 dan Anda hanya menghindari restart aktivitas. Akan tetapi, aplikasi Anda harus selalu 273 bisa dimatikan dan di-restart dengan status sebelumnya tetap utuh, sehingga Anda jangan menganggap teknik 274 ini sebagai jalan keluar untuk mempertahankan status selama daur hidup aktivitas normal. Tidak hanya 275 karena ada perubahan konfigurasi lainnya yang tidak bisa Anda cegah untuk me-restart aplikasi, namun 276 juga karena Anda harus menangani kejadian seperti saat pengguna meninggalkan aplikasi dan 277 dimusnahkan sebelum pengguna kembali ke aplikasi.</p> 278 279 <p>Untuk informasi selengkapnya tentang perubahan konfigurasi yang bisa Anda tangani dalam aktivitas, lihat dokumentasi <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code 280 android:configChanges}</a> dan kelas {@link android.content.res.Configuration} 281 .</p> 282