经典场景:翻转屏幕
public class ConfigChangesActivity extends AppCompatActivity {
private static final String TAG = "ConfigChangesActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, TAG + "onCreate: 已经创建");
setContentView(R.layout.activity_config_changes);
}
/**
* 已开始:Activity会进入到前台
*/
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, TAG + " onStart: 已开始");
}
/**
* 已恢复:可以和用户进行交互
*/
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, TAG + " onResume: 已恢复");
}
/**
* 已暂停:不是被销毁,只是暂时离开Activity
*/
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, TAG + " onPause: 已暂停");
}
/**
* 已停止:Activity页面不会被附加到窗口管理当中,但是Activity本身的一些成员变量、状态还会存在
*/
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, TAG + " onStop: 已停止");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, TAG + " onRestart: 准备重新触发onStart");
}
/**
* Activity被销毁之前,会调用这个方法
*/
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, TAG + " onDestroy: 准备销毁当前页面!");
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
Log.i(TAG, "onConfigurationChanged: ORIENTATION_LANDSCAPE");
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
}
}
}
布局
提问:页面翻转导致Activity被销毁,那么对应的数据也会丢失,怎么解决?
当前Activity一启动就是横屏的状态,landscape 横向格式
android:screenOrientation="landscape"
我就是想让当前的方向随屏幕方向是横屏或者竖屏,并且可以在相应横屏或者竖屏跳转时进行一些代码逻辑的处理
<activity
android:name=".activity.ConfigChangesActivity"
android:configChanges="orientation|screenSize"
android:exported="true" />
android:configChanges="orientation|screenSize"
用于指定当设备发生这些配置变化时,系统不销毁并重建当前 Activity,而是由开发者自己处理配置变化。
在ConfigChangesActivity类中重写onConfigurationChanged方法
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
Log.i(TAG, "onConfigurationChanged: ORIENTATION_LANDSCAPE");
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
}
}
很多商业场景中会使用configChanges,但不是必用的这玩意,这里只是讲的详细一点
显然上面这种方式对于数据丢失是治标不治本的
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.SaveDataActivity">
<EditText
android:id="@+id/et_nick_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:hint="请输入昵称"
app:layout_constraintVertical_bias="0.3"/>
<EditText
android:id="@+id/et_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入年龄"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_nick_name" />
<Button
android:id="@+id/btn_commit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="提交"
app:layout_constraintEnd_toEndOf="@id/et_age"
app:layout_constraintTop_toBottomOf="@id/et_age" />
</androidx.constraintlayout.widget.ConstraintLayout>
我们试想一个场景,运行Activity类,在输入框中输入昵称和密码,返回主屏幕,时间一长,系统可能因为内存不足就把Activity销毁了,那成员变量中保存的数据就没了,在我们的视角当中就是返回页面的时候,之前输入框中输入的数据没了
那怎么才能做到数据的持久存储呢,或者数据恢复呢?
public class SaveDataActivity extends AppCompatActivity {
private static final String TAG = "SaveDataActivity";
private String nickName;
private String age;
private EditText edNickName;
private EditText edAge;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_save_data);
if(savedInstanceState != null){
nickName = savedInstanceState.getString("key_nickName");
age = savedInstanceState.getString("key_age");
Log.i(TAG, "onCreate: 我在OnCreate方法中利用savedInstanceState恢复数据了");
}
edNickName = findViewById(R.id.et_nick_name);
edAge = findViewById(R.id.et_age);
findViewById(R.id.btn_commit).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nickName = edNickName.getText().toString();
age = edAge.getText().toString();
}
});
Log.i(TAG, "onCreate: ");
}
}
/**
* 保存数据
* @param outState Bundle in which to place your saved state.
*
*/
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("key_nickName",nickName);
outState.putString("key_age",age);
Log.i(TAG, "onSaveInstanceState: 保存日志");
}
数据确实被杀掉的情况下,onSaveInstanceState才会被调用
有保存就有恢复方法,两者是相辅相成的
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
nickName = savedInstanceState.getString("key_nickName");
age = savedInstanceState.getString("key_age");
//恢复ui的显示
edNickName.setText(nickName);
edAge.setText(age);
Log.i(TAG, "onRestoreInstanceState: ");
}
if(savedInstanceState != null){
nickName = savedInstanceState.getString("key_nickName");
age = savedInstanceState.getString("key_age");
Log.i(TAG, "onCreate: 我在OnCreate方法中利用savedInstanceState恢复数据了");
}
翻转屏幕,销毁Activity了,单数数据被保存在saveInstanceState中,再次创建横向屏幕Activity时,数据就可以利用saveInstanceState参数进行恢复
以下是利用打断点的方法观察两个key的值
启动的Activity会在放在栈中,最先生成的Activity放在栈底,跳转页面启动新的Activity依次往上叠加,返回时符合栈的后进先出原则
如果是一些不是很重要的,不复杂的数据可以直接在onCreate方法中恢复;
还有你想迅速的恢复数据也可以在OnCreate方法中恢复,不同的场景选择使用不同的方法,需要我们自己抉择
非常复杂的恢复数据的代码建议放到onRestoreInstanceState方法中做