Aktivitas dimulai ulang pada rotasi Android

1380

Dalam aplikasi Android saya, ketika saya memutar perangkat (geser keyboard) maka saya Activityrestart ( onCreatedisebut). Sekarang, ini mungkin memang seharusnya begitu, tetapi saya melakukan banyak pengaturan awal dalam onCreatemetode ini, jadi saya perlu:

  1. Letakkan semua pengaturan awal di fungsi lain sehingga tidak semua hilang pada rotasi perangkat atau
  2. Jadikan jadi onCreatetidak dipanggil lagi dan tata letak hanya menyesuaikan atau
  3. Batasi aplikasi hanya potret sehingga onCreatetidak dipanggil.
Isaac Waller
sumber
4
Ada penjelasan yang agak lengkap tentang bagaimana mempertahankan tugas asinkron yang sudah berjalan lama selama perubahan konfigurasi aktivitas di posting blog ini juga!
Adrian Monk
3
Ini bukan jawaban langsung seperti yang sudah dijawab orang lain, tetapi saya mengundang Anda untuk melihat LogLifeCycle untuk memahami apa yang terjadi di aplikasi Android Anda terkait dengan siklus hidup.
Snicolas

Jawaban:

965

Menggunakan Kelas Aplikasi

Bergantung pada apa yang Anda lakukan dalam inisialisasi Anda, Anda dapat mempertimbangkan membuat kelas baru yang memperluas Applicationdan memindahkan kode inisialisasi Anda ke onCreatemetode yang ditimpa dalam kelas itu.

public class MyApplicationClass extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // TODO Put your application initialization code here.
  }
}

The onCreatedi kelas aplikasi hanya disebut ketika seluruh aplikasi yang dibuat, sehingga Aktivitas restart pada orientasi atau keyboard perubahan visibilitas tidak akan memicu itu.

Adalah praktik yang baik untuk mengekspos instance kelas ini sebagai singleton dan mengekspos variabel aplikasi yang Anda inisialisasi menggunakan getter dan setter.

CATATAN: Anda harus menentukan nama kelas Aplikasi baru Anda di manifes agar dapat didaftarkan dan digunakan:

<application
    android:name="com.you.yourapp.MyApplicationClass"

Bereaksi terhadap Perubahan Konfigurasi [UPDATE: ini sudah ditinggalkan sejak API 13; lihat alternatif yang direkomendasikan ]

Sebagai alternatif lebih lanjut, Anda dapat membuat aplikasi Anda mendengarkan acara yang akan menyebabkan perubahan orientasi dan visibilitas keyboard dimulai ulang - dan menanganinya dalam Kegiatan Anda.

Mulailah dengan menambahkan android:configChangessimpul ke simpul manifes Kegiatan Anda

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

atau untuk Android 3.2 (API level 13) dan yang lebih baru :

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

Kemudian di dalam Activity, ganti onConfigurationChangedmetode tersebut dan panggil setContentViewuntuk memaksa tata letak GUI agar dilakukan kembali dalam orientasi baru.

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}
Reto Meier
sumber
17
Saya rasa pendekatan kedua tidak berhasil. Saya mencobanya; satu Kegiatan dengan EditText. Saya menulis beberapa teks di sana, mengubah orientasi dan teksnya hilang / reset.
Ted
231
Di sini kita berharap kita melihat metode onRotate () di masa depan. Bahkan harus khawatir tentang hal-hal seperti ini — terus terang — membuat frustrasi.
Kelly Sutton
84
Perhatikan bahwa Panduan Dev Android memperingatkan agar tidak menggunakan ini: Catatan: Menggunakan ( android:configChanges) harus dihindari dan digunakan hanya sebagai upaya terakhir. Harap baca Menangani Perubahan Waktu Runtime untuk informasi lebih lanjut tentang cara menangani restart dengan benar karena perubahan konfigurasi. Sebagai pengganti, untuk mempertahankan data di seluruh peristiwa rotasi, mereka tampaknya lebih suka menggunakan onSaveInstanceState Bundle; atau sebagai @ Jon-O menyebutkan , onRetainNonConfigurationInstance.
Jeffro
19
Itu adalah solusi yang buruk, karena hanya bereaksi terhadap perubahan konfigurasi yang diketahui saat ini . Dengan versi Android yang lebih baru, perubahan konfigurasi lainnya dapat terjadi yang tidak dapat ditangkap kode ini (karena harus mencantumkan semua perubahan konfigurasi dalam manifes). Solusi menyelamatkan negara dengan onRetainNonConfigurationChangeslebih toleran terhadap kesalahan dan lurus ke depan.
Bananeweizen
16
Saya pikir Anda harus menambahkan pembaruan ini pada 3.2 untuk jawaban Anda, itu cukup penting (hanya menghadapi masalah itu) dan mungkin diabaikan.
bigstones
185

Pembaruan untuk Android 3.2 dan lebih tinggi:

Perhatian : Dimulai dengan Android 3.2 (API level 13), "ukuran layar" juga berubah ketika perangkat beralih antara orientasi potret dan lanskap. Dengan demikian, jika Anda ingin mencegah restart runtime karena perubahan orientasi ketika mengembangkan untuk API level 13 atau lebih tinggi (sebagaimana dideklarasikan oleh atribut minSdkVersion dan targetSdkVersion), Anda harus memasukkan "screenSize"nilai selain "orientation"nilai. Artinya, Anda harus menyatakan android:configChanges="orientation|screenSize". Namun, jika aplikasi Anda menargetkan API level 12 atau lebih rendah, maka aktivitas Anda selalu menangani perubahan konfigurasi itu sendiri (perubahan konfigurasi ini tidak memulai kembali aktivitas Anda, bahkan ketika berjalan pada perangkat Android 3.2 atau lebih tinggi).

Gorm
sumber
1
Terima kasih atas klarifikasi itu, karena komentar di atas tentang ini hampir membuat saya pergi untuk memeriksanya. Saya saat ini menargetkan API 8 dan kode saya tidak memiliki screenSize pada configChanges dan dapat mengkonfirmasi bahwa itu berfungsi dengan baik (tanpa mengarahkan ulang) pada perangkat yang saya miliki yang menjalankan ICS.
Carl
Terima kasih telah menunjukkan ini, saya hanya punya android: set configChanges = "orientasi | screenSize", dan pengalihan orientasi menciptakan kembali Kegiatan saya, dan untuk kehidupan saya, saya tidak tahu mengapa!
Christopher Perry
5
Menambahkan android: configChanges hanya boleh digunakan sebagai pilihan terakhir . Pertimbangkan untuk menggunakan Fragmentsdan setRetainInstancesebagai gantinya.
Simon Forsberg
Poin kuncinya adalah screenSizeuntuk Android 3.2 dan lebih tinggi, yang menyelesaikan masalah saya, Terima kasih!
fantouch
127

Alih-alih mencoba menghentikan onCreate()pemecatan sama sekali, mungkin mencoba memeriksa Bundle savedInstanceStateyang diteruskan ke acara untuk melihat apakah itu batal atau tidak.

Sebagai contoh, jika saya memiliki beberapa logika yang harus dijalankan ketika Activitybenar-benar dibuat, bukan pada setiap perubahan orientasi, saya hanya menjalankan logika itu onCreate()hanya jika savedInstanceStatenol.

Kalau tidak, saya masih ingin tata letak untuk menggambar dengan benar untuk orientasi.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

        if(savedInstanceState == null){
            setupCloudMessaging();
        }
}

tidak yakin apakah ini adalah jawaban terakhir, tetapi itu bekerja untuk saya.

nebula
sumber
6
dan di mana kamu sebenarnya menyelamatkan negara?
Ewoks
5
ini tampaknya bekerja untuk saya dan tampaknya metode yang paling sederhana. saya perhatikan Anda hanya punya 4 up untuk ini (5 termasuk milik saya) vs 373 untuk ide tentang Aplikasi subklas, yang bagi saya tampaknya jauh lebih rumit. Apakah ada kelemahan metode ini?
steveh
4
Solusi ini sangat cocok untuk saya. saya bisa Intent serverintent = new Intent(MainActivity.this, MessageListener.class);dan startService(serverintent);untuk membuat serverSocket = new ServerSocket(0xcff2);dan Socket client = serverSocket.accept();dengan BufferedReader(new InputStreamReader(client.getInputStream()));dan bisa memutar android saya dan menjaga koneksi klien / server aktif, namun memiliki GUI rotate. Menurut manual, disimpanInstanceState akan diinisialisasi ketika aktivitas terakhir dimatikan.
Fred F
3
Saya tidak mengerti, apa masalahnya? Ini berfungsi dengan baik, dan dengan kompleksitas yang jauh lebih sedikit daripada solusi lainnya.
RTF
3
Ini adalah cara yang benar untuk melakukannya di Android. Cara-cara lain pada dasarnya menangkap rotasi dengan konfigurasi dan semua yang besar, kompleks, dan tidak perlu.
LukeWaggoner
99

apa yang saya lakukan...

di manifes, ke bagian aktivitas, menambahkan:

android:configChanges="keyboardHidden|orientation"

dalam kode untuk aktivitas, diterapkan:

//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
    //get views from ID's
    this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);

    //etc... hook up click listeners, whatever you need from the Views
}

//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    InitializeUI();
}

//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.main);

    InitializeUI();
}
Seseorang disuatu tempat
sumber
3
untuk memperjelas: dengan implementasi saya sekarang Anda dapat memiliki inisialisasi variabel di onCreate () dan onConfigurationChanged () hanya akan dipanggil untuk rotasi layar. Variabel Anda sekarang terisolasi dari rotasi layar ;-) nice and ez
Someone Somewhere
2
Saya melakukan semuanya seperti yang dijelaskan di sini, tetapi saya mendapatkan NullPointerException ketika saya mencoba menekan tombol setelah perubahan orientasi. Apa yang salah?
Finnboy11
5
ingat jawaban saya seperti 3 tahun dan Android terus berkembang ... Simon - apakah Anda memiliki tautan ke kode sampel? Itu yang orang butuhkan.
Seseorang di suatu tempat
3
Ketika peringatan terhadap android: configChanges, @ SimonAndréForsberg sebenarnya hanya memparafrasekan Android docs . Menangani Perubahan Runtime memiliki informasi yang lebih terperinci tentang alternatif (termasuk kode sampel).
Leif Arne Storset
67

Apa yang Anda gambarkan adalah perilaku default. Anda harus mendeteksi dan menangani sendiri acara ini dengan menambahkan:

android:configChanges

ke manifes Anda dan kemudian perubahan yang ingin Anda tangani. Jadi untuk orientasi, Anda akan menggunakan:

android:configChanges="orientation"

dan untuk keyboard yang dibuka atau ditutup Anda akan menggunakan:

android:configChanges="keyboardHidden"

Jika Anda ingin menangani keduanya, Anda bisa memisahkannya dengan perintah pipa seperti:

android:configChanges="keyboardHidden|orientation"

Ini akan memicu metode onConfigurationChanged dalam Kegiatan apa pun yang Anda panggil. Jika Anda mengganti metode, Anda bisa meneruskan nilai-nilai baru.

Semoga ini membantu.

GregD
sumber
2
@ Greg Saya tahu, itulah sebabnya sekarang saat yang tepat untuk memperbaruinya untuk mencerminkan situasi hari ini. Mengingat jumlah upvotes pertanyaan ini, masih dirujuk dari pertanyaan lain pada SO.
Simon Forsberg
48

Saya baru saja menemukan pengetahuan ini:

Untuk menjaga agar Kegiatan tetap hidup melalui perubahan orientasi, dan menanganinya onConfigurationChanged, dokumentasi dan contoh kode di atas menyarankan ini dalam file Manifest:

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

yang memiliki manfaat ekstra yang selalu berhasil.

Pengetahuan bonusnya adalah bahwa menghilangkan yang keyboardHiddentampak logis, tetapi menyebabkan kegagalan dalam emulator (setidaknya untuk Android 2.1): menetapkan hanya orientationakan membuat panggilan emulator baik OnCreatedan onConfigurationChangedkadang - kadang, dan hanya di OnCreatewaktu lain.

Saya belum melihat kegagalan pada perangkat, tetapi saya telah mendengar tentang kegagalan emulator untuk yang lain. Jadi, ini layak untuk didokumentasikan.

Liudvikas Bukys
sumber
14
Perhatian: Dimulai dengan Android 3.2 (API level 13), "ukuran layar" juga berubah ketika perangkat beralih antara orientasi potret dan lanskap. Jadi, jika Anda ingin mencegah restart runtime karena perubahan orientasi ketika mengembangkan untuk API level 13 atau lebih tinggi: android: configChanges = "orientasi | keyboardHidden | screenSize"
Geltrude
Ya, emulator sangat menyebalkan. Anda tidak dapat mengandalkannya untuk melaporkan perubahan konfigurasi dengan akurat.
IgorGanapolsky
Menambahkan android: configChanges hanya boleh digunakan sebagai pilihan terakhir . Pertimbangkan untuk menggunakan Fragmentsdan setRetainInstancesebagai gantinya.
Simon Forsberg
38

Anda mungkin juga mempertimbangkan untuk menggunakan cara platform Android untuk mempertahankan data di seluruh perubahan orientasi: onRetainNonConfigurationInstance()dan getLastNonConfigurationInstance().

Ini memungkinkan Anda untuk mempertahankan data di seluruh perubahan konfigurasi, seperti informasi yang mungkin Anda peroleh dari server yang diambil atau sesuatu yang telah dihitung onCreateatau sejak saat itu, sementara itu juga memungkinkan Android untuk menata ulang Anda Activitymenggunakan file xml untuk orientasi yang sekarang digunakan .

Lihat di sini atau di sini .

Perlu dicatat bahwa metode ini sekarang sudah usang (walaupun masih lebih fleksibel daripada menangani perubahan orientasi sendiri seperti kebanyakan solusi di atas sarankan) dengan rekomendasi bahwa setiap orang beralih ke Fragmentsdan alih-alih menggunakan setRetainInstance(true)pada setiap Fragmentyang ingin Anda pertahankan.

Jon O
sumber
3
Saya benar-benar berpikir Fragmen dan setRetainInstance adalah cara terbaik (dan direkomendasikan oleh Google) untuk melakukan ini, +1 untuk Anda dan -1 untuk yang lainnya. Menambahkan android: configChanges hanya boleh digunakan sebagai pilihan terakhir
Simon Forsberg
32

Pendekatan ini bermanfaat tetapi tidak lengkap saat menggunakan Fragmen.

Fragmen biasanya dibuat ulang pada perubahan konfigurasi. Jika Anda tidak ingin ini terjadi, gunakan

setRetainInstance(true); dalam konstruktor Fragmen

Ini akan menyebabkan fragmen dipertahankan selama perubahan konfigurasi.

http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)

Abdo
sumber
7
Sepakat. Dengan API Android terbaru, tampaknya Fragmen adalah cara yang tepat untuk menangani ini. Saya belum mencobanya sendiri, tetapi dari apa yang saya kumpulkan membaca halaman ini , pada dasarnya Anda memindahkan 99% dari apa yang Anda gunakan untuk mengimplementasikan dalam suatu Kegiatan ke dalam subkelas Fragmen, kemudian menambahkan Fragmen itu ke dalam Kegiatan. Aktivitas masih akan dihancurkan dan dibuat ulang pada rotasi layar, tetapi Anda dapat secara khusus memberitahu android untuk tidak menghancurkan Fragment menggunakan setRetainInstance()metode @Abdo yang disebutkan.
brianmearns
25

Saya hanya menambahkan

     android:configChanges="keyboard|keyboardHidden|orientation"

dalam file manifes dan tidak menambahkanonConfigurationChanged metode apa pun dalam aktivitas saya.

Jadi setiap kali keyboard meluncur keluar atau tidak terjadi apa-apa .

bass.t
sumber
ditambahkan ke <application ...android:configChanges="keyboard|keyboardHidden|orientation">dan itu berfungsi. Pengaturan saya di build.gradle:minSdkVersion 15, compileSdkVersion 23, buildToolsVersion "23.0.2"
Junior Mayhé
19

The onCreateMetode ini masih disebut bahkan ketika Anda mengubah orientationandroid. Jadi memindahkan semua fungsi berat ke metode ini tidak akan membantu Anda

Ganesh Krishnan
sumber
18

Masukkan kode di bawah ini ke dalam <activity>tag Anda di Manifest.xml:

android:configChanges="screenLayout|screenSize|orientation"
Vaishali Sutariya
sumber
17
 onConfigurationChanged is called when the screen rotates. 
 (onCreate is no longer called when screen rotates due to manifest, see:  
 android:configChanges)

Apa bagian dari manifes yang mengatakan "jangan panggil onCreate()"?

Juga, dokumen Google mengatakan untuk menghindari penggunaan android:configChanges(kecuali sebagai upaya terakhir) .... Tapi kemudian metode alternatif yang mereka sarankan semua DO gunakan android:configChanges.

Sudah pengalaman saya bahwa emulator SELALU memanggil onCreate()rotasi.
Tapi perangkat 1-2 yang saya jalankan kode yang sama ... tidak. (Tidak yakin mengapa akan ada perbedaan.)

Carol
sumber
16

Sangat sederhana lakukan saja langkah-langkah berikut ini:

<activity
    android:name=".Test"
    android:configChanges="orientation|screenSize"
    android:screenOrientation="landscape" >
</activity>

Ini bekerja untuk saya:

Catatan: orientasi tergantung pada penggantian Anda

ManiTeja
sumber
15

Perubahan yang harus dilakukan dalam manifes Android adalah:

android:configChanges="keyboardHidden|orientation" 

Tambahan yang harus dilakukan di dalam aktivitas adalah:

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();
    }
}
sumand pandey
sumber
15

Tambahkan baris ini ke manifes Anda: -

android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"

dan cuplikan ini ke aktivitas: -

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
Parin Parikh
sumber
14

Ada beberapa cara untuk melakukan ini:

Simpan Status Aktivitas

Anda dapat menyimpan status aktivitas di onSaveInstanceState.

@Override
public void onSaveInstanceState(Bundle outState) {
    /*Save your data to be restored here
    Example : outState.putLong("time_state", time); , time is a long variable*/
    super.onSaveInstanceState(outState);
}

dan kemudian gunakan bundleuntuk memulihkan keadaan.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(savedInstanceState!= null){
       /*When rotation occurs
        Example : time = savedInstanceState.getLong("time_state", 0); */
    } else {
      //When onCreate is called for the first time
    }
}

Tangani perubahan orientasi sendiri

Alternatif lain adalah menangani perubahan orientasi sendiri. Tetapi ini tidak dianggap sebagai praktik yang baik.

Tambahkan ini ke file manifes Anda.

android:configChanges="keyboardHidden|orientation"

untuk Android 3.2 dan yang lebih baru:

android:configChanges="keyboardHidden|orientation|screenSize"

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

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Handle rotation from landscape to portarit mode here
    } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
        //Handle rotation from portrait to landscape mode here
    }
}

Batasi rotasi

Anda juga dapat membatasi aktivitas Anda ke mode potret atau lansekap untuk menghindari rotasi.

Tambahkan ini ke tag aktivitas di file manifes Anda:

        android:screenOrientation="portrait"

Atau laksanakan ini secara terprogram dalam aktivitas Anda:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Piyush
sumber
11

Cara yang saya temukan untuk melakukan ini adalah menggunakan onRestoreInstanceStatedan onSaveInstanceStateperistiwa untuk menyimpan sesuatu di Bundle(bahkan jika Anda tidak memerlukan variabel disimpan, cukup masukkan sesuatu di sana sehingga Bundletidak kosong). Kemudian, pada onCreatemetode, periksa untuk melihat apakah Bundlekosong, dan jika ya, maka lakukan inisialisasi, jika tidak, maka lakukanlah.

Shaun
sumber
11

Meskipun itu bukan "cara Android", saya mendapatkan hasil yang sangat baik dengan menangani perubahan orientasi sendiri dan hanya memposisikan ulang widget dalam tampilan untuk mempertimbangkan orientasi yang diubah. Ini lebih cepat daripada pendekatan lain, karena pandangan Anda tidak harus disimpan dan dipulihkan. Ini juga memberikan pengalaman yang lebih mulus bagi pengguna, karena widget yang diposisikan ulang adalah widget yang sama persis, hanya dipindahkan dan / atau diubah ukurannya. Tidak hanya status model, tetapi juga status tampilan, dapat dipertahankan dengan cara ini.

RelativeLayoutterkadang bisa menjadi pilihan yang baik untuk tampilan yang harus mengubah arah dari waktu ke waktu. Anda hanya menyediakan satu set params tata letak potret dan satu set params tata letak lanskap, dengan aturan posisi relatif yang berbeda pada masing-masing, untuk setiap widget anak. Kemudian, dalam onConfigurationChanged()metode Anda, Anda memberikan yang sesuai untuk setLayoutParams()panggilan pada setiap anak. Jika kontrol anak mana pun itu sendiri perlu diorientasi ulang secara internal , Anda cukup memanggil metode pada anak itu untuk melakukan reorientasi. Anak itu sama panggilan metode pada salah satu nya kontrol anak yang perlu reorientasi internal dan sebagainya.

Carl
sumber
Saya akan senang melihat beberapa contoh kode ini, nampak brilian!
Henrique de Sousa
8

Setiap kali ketika layar diputar, aktivitas yang dibuka selesai dan onCreate () dipanggil lagi.

1. Anda dapat melakukan satu hal, menyimpan status aktivitas saat layar diputar sehingga, Anda dapat memulihkan semua hal lama saat aktivitas onCreate () dipanggil lagi. Lihat ini tautan

2. Jika Anda ingin mencegah memulai kembali aktivitas, cukup tempatkan baris berikut di file manifest.xml Anda.

  <activity android:name=".Youractivity"
  android:configChanges="orientation|screenSize"/>
Mansuu ....
sumber
7

Anda perlu menggunakan metode onSavedInstanceState untuk menyimpan semua nilai ke parameternya yaitu bundle

@Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        outPersistentState.putBoolean("key",value);
    }

dan gunakan

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.getBoolean("key");
    } 

untuk retrive dan mengatur nilai untuk melihat objek itu akan menangani rotasi layar

koteswara DK
sumber
Ini membutuhkan API level 22.
Mohammad Afrashteh
6

Catatan: Saya memposting jawaban ini jika seseorang di masa depan menghadapi masalah yang sama dengan saya. Bagi saya, baris berikut tidak cukup:

android:configChanges="orientation"

Ketika saya memutar layar, metode `onConfigurationChanged (Configuration newConfig) tidak dipanggil.

Solusi: Saya juga harus menambahkan "screenSize" bahkan jika masalahnya ada hubungannya dengan orientasi. Jadi di file AndroidManifest.xml -, tambahkan ini:

android:configChanges="keyboardHidden|orientation|screenSize"

Kemudian implementasikan metode tersebut onConfigurationChanged(Configuration newConfig)

iHank
sumber
5

Di bagian aktivitas manifest, tambahkan:

android:configChanges="keyboardHidden|orientation"
Richard K Maleho
sumber
5

Tambahkan baris ini dalam manifes: android:configChanges="orientation|screenSize"

Vikramsinh Gaikwad
sumber
4

Orang-orang mengatakan bahwa Anda harus menggunakannya

android:configChanges="keyboardHidden|orientation"

Tetapi cara terbaik dan paling profesional untuk menangani rotasi di Android adalah dengan menggunakan kelas Loader. Ini bukan kelas yang terkenal (saya tidak tahu mengapa), tetapi ini jauh lebih baik daripada AsyncTask. Untuk informasi lebih lanjut, Anda dapat membaca tutorial Android yang ada di kursus Android Udacity.

Tentu saja, sebagai cara lain, Anda bisa menyimpan nilai atau tampilan dengan onSaveInstanceState dan membacanya dengan onRestoreInstanceState. Terserah Anda kok.

Theo
sumber
Ya, mari kita tambahkan sekumpulan kode tambahan agar terlihat "profesional". Atau bagaimana dengan tetap berpegang pada cara cepat, mudah, benar dan mencoba melakukannya dengan atribut configurationChanges.
AndroidDev
3

Setelah beberapa saat coba-coba, saya menemukan solusi yang sesuai dengan kebutuhan saya dalam sebagian besar situasi. Ini Kodenya:

Konfigurasi manifes:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.pepperonas.myapplication">

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

Aktifitas utama:

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    private Fragment mFragment;

    private int mSelected = -1;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate  " + "");

        // null check not realy needed - but just in case...
        if (savedInstanceState == null) {

            initUi();

            // get an instance of FragmentTransaction from your Activity
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

            /*IMPORTANT: Do the INITIAL(!) transaction only once!
            * If we call this everytime the layout changes orientation,
            * we will end with a messy, half-working UI.
            * */
            mFragment = FragmentOne.newInstance(mSelected = 0);
            fragmentTransaction.add(R.id.frame, mFragment);
            fragmentTransaction.commit();
        }
    }


    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.d(TAG, "onConfigurationChanged  " +
                   (newConfig.orientation
                    == Configuration.ORIENTATION_LANDSCAPE
                    ? "landscape" : "portrait"));

        initUi();

        Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
        makeFragmentTransaction(mSelected);
    }


    /**
     * Called from {@link #onCreate} and {@link #onConfigurationChanged}
     */
    private void initUi() {
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate  instanceState == null / reinitializing..." + "");
        Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
        Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
        btnFragmentOne.setOnClickListener(this);
        btnFragmentTwo.setOnClickListener(this);
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME!!!");
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME, AS WELL!!!");
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume  " + "");
    }


    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause  " + "");
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy  " + "");
    }


    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.btn_fragment_one:
                Log.d(TAG, "onClick btn_fragment_one " + "");
                makeFragmentTransaction(0);
                break;

            case R.id.btn_fragment_two:
                Log.d(TAG, "onClick btn_fragment_two " + "");
                makeFragmentTransaction(1);
                break;

            default:
                Log.d(TAG, "onClick  null - wtf?!" + "");
        }
    }


    /**
     * We replace the current Fragment with the selected one.
     * Note: It's called from {@link #onConfigurationChanged} as well.
     */
    private void makeFragmentTransaction(int selection) {

        switch (selection) {
            case 0:
                mFragment = FragmentOne.newInstance(mSelected = 0);
                break;
            case 1:
                mFragment = FragmentTwo.newInstance(mSelected = 1);
                break;
        }

        // Create new transaction
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(R.id.frame, mFragment);

        /*This would add the Fragment to the backstack...
        * But right now we comment it out.*/
        //        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

}

Dan sampel Fragmen:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author Martin Pfeffer (pepperonas)
 */
public class FragmentOne extends Fragment {

    private static final String TAG = "FragmentOne";


    public static Fragment newInstance(int i) {
        Fragment fragment = new FragmentOne();
        Bundle args = new Bundle();
        args.putInt("the_id", i);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView  " + "");
        return inflater.inflate(R.layout.fragment_one, container, false);
    }

}

Dapat ditemukan di github .

Martin Pfeffer
sumber
3

Gunakan orientationpendengar untuk melakukan tugas yang berbeda pada orientasi yang berbeda.

@Override
public void onConfigurationChanged(Configuration myConfig) 
{
    super.onConfigurationChanged(myConfig);
    int orient = getResources().getConfiguration().orientation; 
    switch(orient) 
    {
       case Configuration.ORIENTATION_LANDSCAPE:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    break;
       case Configuration.ORIENTATION_PORTRAIT:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    break;
       default:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
}
Akshay Paliwal
sumber
3

Masukkan kode di bawah ini ke Activitydalam Android Manifest.

android:configChanges="orientation"

Ini tidak akan memulai kembali aktivitas Anda ketika Anda akan mengubah orientasi.

Pratik Dasa
sumber
2
@Mavamaarten Mungkin karena seperti yang telah ditunjukkan orang lain, ini merupakan praktik buruk dan sepuluh jawaban lainnya telah membahas hal ini.
MikkoP
3

Perbaiki orientasi layar (lanskap atau potret) di AndroidManifest.xml

android:screenOrientation="portrait" atau android:screenOrientation="landscape"

untuk ini onResume()metode Anda tidak dipanggil.

Brajendra Pandey
sumber
5
bagaimana memperbaiki sesuatu adalah jawabannya? Mengapa perangkat kami dapat diputar jika kami mengunci pengguna yang menggunakannya?
Reinherd
3

Salah satu komponen terbaik dari arsitektur Android yang diperkenalkan oleh Google akan memenuhi semua persyaratan Anda yaitu ViewModel.

Itu dirancang untuk menyimpan dan mengelola data terkait UI dengan cara siklus hidup plus yang akan memungkinkan data untuk bertahan saat layar berputar

class MyViewModel : ViewModel() {

Silakan lihat ini: https://developer.android.com/topic/libraries/architecture/viewmodel

Android Geek
sumber