设备旋转后恢复数据的问题
Issue with restoring data after device was rotated
我查了很多和我类似问题的其他答案,但还是不明白那里出了什么问题。
我有activity和片段
main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/fragment_container"
android:background="#CCC"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
private LinearLayout fragmentContainer;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("LOG", "onCreate");
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
openFragment();
} else {
replaceFragment();
}
}
private void openFragment() {
final LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setId(12345);
getFragmentManager().beginTransaction().add(ll.getId(),
new SimpleFragment(), "SimpleFragment").commit();
fragmentContainer = (LinearLayout) findViewById(R.id.fragment_container);
fragmentContainer.addView(ll);
}
private void replaceFragment() {
final LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setId(12345);
getFragmentManager().beginTransaction().replace(ll.getId(),
new SimpleFragment(), "SimpleFragment").commit();
fragmentContainer = (LinearLayout) findViewById(R.id.fragment_container);
fragmentContainer.addView(ll);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("LOG", "onDestroy");
}
}
和简单片段
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Simple Fragment"/>
</LinearLayout>
public class SimpleFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
String aaa = savedInstanceState.getString("AAA");
Toast.makeText(getActivity(), aaa, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "NULL", Toast.LENGTH_SHORT).show();
}
Log.d("LOG", "onCreate");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d("LOG", "fragment onCreateView");
return inflater.inflate(R.layout.simple_fragment, null);
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d("LOG", "fragment onDestroyView");
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("AAA", "Hello");
}
}
那么问题是什么:
当我旋转设备时,应用程序应该保存一个状态然后恢复它(让我们假设一些变量)。
旋转后立即执行 onSaveInstanceState。
数据已保存。
然后执行fragment的onCreate,恢复数据
没关系。这是预期的行为。
但由于 activity 也被重新创建,片段应该再次添加(替换)。结果片段的 onCreate 再次执行。我看到没有保存数据的片段。我看到新创建的片段。
如何避免这种创建?
我旋转设备,数据被保存然后恢复。片段在 activity 上可见且数据已恢复。
那么在activity中添加片段的算法是什么,以便在旋转后不添加片段并避免重新创建?
从布局添加
一般来说,您不需要从代码中为您的片段添加额外的容器。添加片段的最简单方法是在布局中使用 android:id
属性!!!
定义 <fragment .../>
您的案例示例:
public class MainActivity extends Activity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("LOG", "onCreate");
setContentView(R.layout.activity_main);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("LOG", "onDestroy");
}
}
和main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#CCC"
android:orientation="vertical"
>
<fragment
android:id="@+id/fragment"
android:name="your.package.name.SimpleFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
</LinearLayout>
片段代码和布局不需要任何更改。
从代码添加
如果您确实需要从代码中添加它,则不需要从代码中添加额外的容器。如果是首次启动,只需添加片段 - 系统会为您完成后。
您的案例示例:
public class MainActivity extends Activity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("LOG", "onCreate");
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
openFragment();
}
}
private void openFragment() {
getFragmentManager().beginTransaction().add(R.id.fragment_container,
new SimpleFragment(), "SimpleFragment").commit();
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("LOG", "onDestroy");
}
}
和main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/fragment_container"
android:background="#CCC"/>
</LinearLayout>
片段代码和布局不需要任何更改。
我查了很多和我类似问题的其他答案,但还是不明白那里出了什么问题。
我有activity和片段
main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/fragment_container"
android:background="#CCC"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
private LinearLayout fragmentContainer;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("LOG", "onCreate");
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
openFragment();
} else {
replaceFragment();
}
}
private void openFragment() {
final LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setId(12345);
getFragmentManager().beginTransaction().add(ll.getId(),
new SimpleFragment(), "SimpleFragment").commit();
fragmentContainer = (LinearLayout) findViewById(R.id.fragment_container);
fragmentContainer.addView(ll);
}
private void replaceFragment() {
final LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setId(12345);
getFragmentManager().beginTransaction().replace(ll.getId(),
new SimpleFragment(), "SimpleFragment").commit();
fragmentContainer = (LinearLayout) findViewById(R.id.fragment_container);
fragmentContainer.addView(ll);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("LOG", "onDestroy");
}
}
和简单片段
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Simple Fragment"/>
</LinearLayout>
public class SimpleFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
String aaa = savedInstanceState.getString("AAA");
Toast.makeText(getActivity(), aaa, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "NULL", Toast.LENGTH_SHORT).show();
}
Log.d("LOG", "onCreate");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d("LOG", "fragment onCreateView");
return inflater.inflate(R.layout.simple_fragment, null);
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d("LOG", "fragment onDestroyView");
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("AAA", "Hello");
}
}
那么问题是什么:
当我旋转设备时,应用程序应该保存一个状态然后恢复它(让我们假设一些变量)。
旋转后立即执行 onSaveInstanceState。 数据已保存。 然后执行fragment的onCreate,恢复数据
没关系。这是预期的行为。
但由于 activity 也被重新创建,片段应该再次添加(替换)。结果片段的 onCreate 再次执行。我看到没有保存数据的片段。我看到新创建的片段。
如何避免这种创建?
我旋转设备,数据被保存然后恢复。片段在 activity 上可见且数据已恢复。
那么在activity中添加片段的算法是什么,以便在旋转后不添加片段并避免重新创建?
从布局添加
一般来说,您不需要从代码中为您的片段添加额外的容器。添加片段的最简单方法是在布局中使用 android:id
属性!!!
<fragment .../>
您的案例示例:
public class MainActivity extends Activity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("LOG", "onCreate");
setContentView(R.layout.activity_main);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("LOG", "onDestroy");
}
}
和main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#CCC"
android:orientation="vertical"
>
<fragment
android:id="@+id/fragment"
android:name="your.package.name.SimpleFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
</LinearLayout>
片段代码和布局不需要任何更改。
从代码添加
如果您确实需要从代码中添加它,则不需要从代码中添加额外的容器。如果是首次启动,只需添加片段 - 系统会为您完成后。
您的案例示例:
public class MainActivity extends Activity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("LOG", "onCreate");
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
openFragment();
}
}
private void openFragment() {
getFragmentManager().beginTransaction().add(R.id.fragment_container,
new SimpleFragment(), "SimpleFragment").commit();
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("LOG", "onDestroy");
}
}
和main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/fragment_container"
android:background="#CCC"/>
</LinearLayout>
片段代码和布局不需要任何更改。