横竖屏切换状态保持
掌握手机横竖屏切换时Activity的各种变化,以及掌握如何保护横竖屏切换前的数据和恢复现场
学习内容
- Activity的状态
- ? 运行时系统配置变更
- ? 应对配置变更
- ? 保存和恢复Activity的状态
- ? Fragment状态
带着问题学习!
- Activity的哪些状态需要被保存和恢复?
- ? 发生运行时系统配置变更时系统会做什么?? 如何应对系统配置变更?
- ? 如何保存和恢复Activity的状态?
- ? 如何保持Fragment的状态?
一、运行时系统配置变更
有以下三种情况使系统配置变更
- ? 屏幕方向从竖屏变为横屏?
- 键盘可见性从可见到不可见?
- 系统语言从英文切换到中文
二、现场保护Activity方式1(屏幕变换)
屏幕变化时系统会做什么??
- ? 销毁正在运行的Activity对象?
- 创建一个新的Activity对象
一、应对配置变更-限定方向
在AndroidManifest.xml中的Activity标签中写
android:screenOrientation="portrait" 限定activity只支持竖屏,不支持横屏。
<!--android:screenOrientation="portrait" 限定activity只支持竖屏-->
<activity
android:name=".Main2Activity"
android:screenOrientation="portrait"></activity>
二、应用配置变更-自己处理
在AndroidManifest.xml中的Activity标签中写
android:configChanges="orientation|screenSize|keyboardHidden"
自己处理屏幕发生改变后的方向,屏幕位置,键盘的可见性,实现自己处理横竖屏变化,无需系统重启Activity。
<!-- android:configChanges="orientation|screenSize|keyboardHidden" 自己处理屏幕翻转时自己处理-->
<activity
android:name=".Main2Activity"
android:configChanges="orientation|screenSize|keyboardHidden"></activity>
三、应用配置变更-让系统处理配置变更
取消在AndroidManifest.xml中上述的操作,让系统自己配置
例如,我们想要实现竖屏显示布局1,横屏显示布局2,那么就要通过以下重写的方法了的bundle来保存状态
- ?onSaveInstanceState?
- onCreate
- ? onRestoreInstanceState
分析保存时机:
onSaveInstanceState的执行
- ? 按HOME键时?
- 被来电覆盖时
- 屏幕旋转
? 用户按返回键时
四、保存与恢复状态
系统配置发生改变后,视图是系统默认保存的,但是不会保存成员状态,但是要注意以下几点:
- ? 组件必须设置了id属性
- 实现了onSaveInstanceState回调 (利用Bundle实现保存)在状态改变时执行,将这个bundle传给onRestoreInstanceState
- ? 实现了onRestoreInstanceState回调(利用Bundle实现恢复)在新建或者重启Activity后会执行
- 可以选择再onRestoreInstanceState进行恢复状态,也可以在onCreate中进行恢复,注意判空!
对象不会保存,所以自己重写以上两种方法来put、get。
private static final String TAG = "Main2Activity";
/**
* 可以在oncreate恢复
*
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
if (savedInstanceState != null) {
Log.e(TAG, "onCreate: " + Integer.toHexString(savedInstanceState.hashCode()));
Log.e(TAG, "onCreate中拿值:" + savedInstanceState.get("key"));
}
}
/**
* 也可以在onRestoreInstanceState中恢复
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.e(TAG, "onRestoreInstanceState: " +Integer.toHexString(savedInstanceState.hashCode()));
Log.e(TAG, "onRestoreInstanceState中拿值: " + savedInstanceState.get("key"));
}
/**
* 实现系统配置更改后状态的保存
*
* @param outState
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("key", "value");
Log.e(TAG, "onSaveInstanceState: " + Integer.toHexString(outState.hashCode()) + " ");
}
结果:
E/Main2Activity: onSaveInstanceState: dcb5ea6
E/Main2Activity: onCreate: dcb5ea6
onCreate中拿值:value
E/Main2Activity: onRestoreInstanceState: dcb5ea6
onRestoreInstanceState中拿值: value
五、现场保护Fragment
一、保持Fragment对象
- ? 扩展Fragment(自定义Fragment)
- ? 在onCreate函数里调用setRetainInstance(true);
- ? 把Fragment对象添加到Activity中
- ? 当Activity重启时,通过FragmentManager获取此Fragment对象
这是一个点击Fragment里面button进行累加,然后旋转屏幕看是否 能保存fragment的状态
MyFragment.java中
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
public class MyFragment extends Fragment {
private static final String TAG = "BlankFragment-vv";
private int countNum;
public MyFragment() {
// Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: ");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_blank, container, false);
final TextView tv_count = view.findViewById(R.id.tv_count);
tv_count.setText(String.valueOf(countNum));
final Button bt_add = view.findViewById(R.id.bt_start);
bt_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv_count.setText(String.valueOf(++countNum));
}
});
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
MainActivty中将上面的Fragment添加进来
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity-vv";
private Fragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//不需要布局文件
//1。新建fragment对象
fragment = new MyFragment();
FragmentManager fm = getSupportFragmentManager();
//添加到这个activity中
fm.beginTransaction()
.replace(android.R.id.content, fragment, "MyFragment")
.commit();
Log.d(TAG, "onCreate: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}
当进行屏幕翻转的时候
11-25 11:15:56.715 6011-6011/com.demo.fragmentdemo2 D/MainActivity-vv: onCreate:
11-25 11:15:56.745 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onCreate:
11-25 11:16:03.863 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onDestroy:
11-25 11:16:03.863 6011-6011/com.demo.fragmentdemo2 D/MainActivity-vv: onDestroy:
11-25 11:16:03.892 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onCreate:
11-25 11:16:03.892 6011-6011/com.demo.fragmentdemo2 D/MainActivity-vv: onCreate:
11-25 11:16:03.944 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onCreate:
11-25 11:16:03.945 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onDestroy:
Fragment和Activity被销毁又重新创建了,上面已经讲过如何保存Activity的状态了,那么Fragment的状态怎么保存呢?
1.在MyFragment 的onCreate中调用 setRetainInstance(true);
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//告诉系统我要保存fragment对象
setRetainInstance(true);
Log.d(TAG, "onCreate: ");
}
2.在MainActivity中的Oncreate方法中
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//不需要布局文件
FragmentManager fm = getSupportFragmentManager();
//通过第一次加载fragment设置的tag找到fragment
fragment = fm.findFragmentByTag("MyFragment");
if (fragment == null) {
//1.如果找不到才新建
fragment = new MyFragment();
//添加到这个activity中
fm.beginTransaction()
.replace(android.R.id.content, fragment, "MyFragment")
.commit();
}
Log.d(TAG, "onCreate: ");
}
结果:Fragment没有被销毁和新建
11-25 11:21:23.959 6554-6554/? D/MainActivity-vv: onCreate:
11-25 11:21:23.991 6554-6554/? D/MyFragment-vv: onCreate:
11-25 11:21:38.448 6554-6554/com.demo.fragmentdemo2 D/MainActivity-vv: onDestroy:
11-25 11:21:38.514 6554-6554/com.demo.fragmentdemo2 D/MainActivity-vv: onCreate:
二、保存和恢复Fragment的状态
Activity好Fragment有何共同点和不同点在保存状态的时候:
相同点:和activity一样可以在? onSaveInstanceState?中保存fragment的状态
不同点:fragment 在onActivityCreated或oncreate方法中恢复状态没onRestoreInstanceState的方法,而Acitivity中有