Menggunakan paket kompatibilitas untuk menargetkan 2.2 menggunakan Fragmen.
Setelah mengodekan ulang aktivitas untuk menggunakan fragmen dalam aplikasi, saya tidak bisa mendapatkan perubahan orientasi / manajemen status yang berfungsi, jadi saya telah membuat aplikasi uji kecil dengan satu FragmentActivity dan satu Fragmen.
Log dari perubahan orientasi itu aneh, dengan beberapa panggilan ke fragmen OnCreateView.
Saya jelas kehilangan sesuatu - seperti melepaskan fragmen dan memasangnya kembali daripada membuat contoh baru, tetapi saya tidak dapat melihat dokumentasi yang akan menunjukkan di mana kesalahan saya.
Adakah yang bisa menjelaskan kesalahan saya di sini. Terima kasih
Lognya adalah sebagai berikut setelah orientasi berubah.
Initial creation
12-04 11:57:15.808: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:15.945: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:16.081: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 1
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:57:39.031: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.167: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 2
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.361: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Aktivitas Utama (FragmentActivity)
public class FragmentTestActivity extends FragmentActivity {
/** Called when the activity is first created. */
private static final String TAG = "FragmentTest.FragmentTestActivity";
FragmentManager mFragmentManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG, "onCreate");
mFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
Dan fragmennya
public class FragmentOne extends Fragment {
private static final String TAG = "FragmentTest.FragmentOne";
EditText mEditText;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "OnCreateView");
View v = inflater.inflate(R.layout.fragmentonelayout, container, false);
// Retrieve the text editor, and restore the last saved state if needed.
mEditText = (EditText)v.findViewById(R.id.editText1);
if (savedInstanceState != null) {
Log.d(TAG, "OnCreateView->SavedInstanceState not null");
mEditText.setText(savedInstanceState.getCharSequence("text"));
}
else {
Log.d(TAG,"OnCreateView->SavedInstanceState null");
}
return v;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "FragmentOne.onSaveInstanceState");
// Remember the current text, to restore if we later restart.
outState.putCharSequence("text", mEditText.getText());
}
Nyata
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".activities.FragmentTestActivity"
android:configChanges="orientation">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Jawaban:
Anda melapisi Fragmen Anda satu di atas yang lain.
Saat terjadi perubahan konfigurasi, Fragmen lama menambahkan dirinya sendiri ke Aktivitas baru saat dibuat ulang. Ini adalah rasa sakit yang luar biasa di bagian belakang hampir sepanjang waktu.
Anda dapat menghentikan kesalahan yang terjadi dengan menggunakan Fragmen yang sama daripada membuat ulang yang baru. Cukup tambahkan kode ini:
Berhati-hatilah: masalah akan muncul jika Anda mencoba dan mengakses Tampilan Aktivitas dari dalam Fragmen karena siklus proses akan berubah secara halus. (Mendapatkan Views dari Aktivitas induk dari Fragmen tidaklah mudah).
sumber
"when the activity is destroyed, so are all fragments"
:? Sejak"When the screen orientation changes, the system destroys and recreates the activity [...]"
.Mengutip buku ini , "untuk memastikan pengalaman pengguna yang konsisten, Android mempertahankan tata letak Fragmen dan back-stack terkait saat Aktivitas dimulai ulang karena perubahan konfigurasi." (hlm. 124)
Dan cara untuk mendekatinya adalah dengan terlebih dahulu memeriksa apakah tumpukan belakang Fragmen telah diisi, dan membuat instance fragmen baru hanya jika belum:
sumber
Metode onCreate () aktivitas Anda dipanggil setelah orientasi berubah seperti yang Anda lihat. Jadi, jangan jalankan FragmentTransaction yang menambahkan Fragment setelah orientasi berubah dalam aktivitas Anda.
Fragmen harus dan tidak boleh diubah.
sumber
Anda dapat
@Override
menggunakan FragmentActivityonSaveInstanceState()
. Harap pastikan untuk tidak memanggilsuper.onSaveInstanceState()
dalam metode ini.sumber
Kami harus selalu mencoba untuk mencegah pengecualian nullpointer, jadi kami harus memeriksa terlebih dahulu di metode saveinstance untuk informasi bundel. untuk penjelasan singkatnya cek link blog ini
sumber
Jika Anda hanya melakukan sebuah proyek, maka manajer proyek mengatakan Anda perlu mencapai layar fungsi switching, tetapi Anda tidak ingin layar switching memuat tata letak yang berbeda (dapat membuat tata letak dan sistem tata letak-port.
Anda secara otomatis akan menentukan status layar, memuat tata letak yang sesuai), karena kebutuhan untuk menginisialisasi ulang aktivitas atau fragmen, pengalaman pengguna tidak baik, tidak langsung pada sakelar layar, saya lihat? Url = YgNfP-vHy-Nuldi7YHTfNet3AtLdN-w__O3z1wLOnzr3wDjYo7X7PYdNyhw8R24ZE22xiKnydni7R0r35s2fOLcHOiLGYT9Qh_f0000aqtytJ199 & wd
Premisnya adalah bahwa layout Anda menggunakan bobot cara layout layout_weight, sebagai berikut:
Jadi pendekatan saya adalah, saat pengalihan layar, tidak perlu memuat tata letak baru dari file tampilan, ubah tata letak dalam bobot dinamis onConfigurationChanged, langkah-langkah berikut: 1 set pertama: AndroidManifest.xml di atribut aktivitas: android: configChanges = "keyboardHidden | orientasi | screenSize" Untuk mencegah peralihan layar, hindari memuat ulang, agar dapat memantau aktivitas atau fragmen penulisan ulang onConfigurationChanged 2 dalam metode onConfigurationChanged.
sumber
Saat perubahan konfigurasi, framework akan membuat instance baru dari fragmen untuk Anda dan menambahkannya ke aktivitas. Jadi, alih-alih ini:
melakukan hal ini:
Harap diperhatikan bahwa framework menambahkan instance baru FragmentOne saat orientasi berubah kecuali Anda memanggil setRetainInstance (true), yang dalam hal ini akan menambahkan instance lama FragmentOne.
sumber