Home | History | Annotate | Download | only in resources
      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()}&mdash;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     &#64;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     &#64;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     &#64;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 &lt;activity&gt;}</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 &lt;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 &#64;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