研究:Android中 Activity生命周期的变化及横竖屏切换时数据一致性的保持。
- Android 生命周期:7种生命周期,如下图。
- 同一个Activity横竖屏切换时:页面的变化、生命周期的变化。
- 横竖屏切换时,页面数据一致性的保持。
一、Activity生命周期的效果图如下:
各生命周期的描述略 。。。
创建生命周期的类:LifeCycleActivity.java
/**
* Activity生命周期
* 使用@Override注解,就是要求编译器保证当前子类拥有你要覆盖的方法
*/
public class LifeCycleActivity extends AppCompatActivity {
private TextView text_show;
private Button btn_add;
private static final String KEY_INDEX = "index";//标记key
private static final String TAG = "LifeCycleActivity";
private int number =0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_life_cycle);
Log.d(TAG, "onCreate() 方法");
text_show = (TextView) findViewById(R.id.text_show);
btn_add = (Button) findViewById(R.id.btn_add);
//点击按钮,展示的数据+1
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
number++;
text_show.setText(number+"");
}
});
}
@Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart() 方法");
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume() 方法");
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause() 方法");
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop() 方法");
}
@Override
public void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart() 方法");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() 方法");
}
}
二、Activity横竖屏切换时的生命周期的变化:
Activity从竖向转成横向时,实际上就是 竖向的Activity先销毁,然后重新生成横向的Activity页面,通过下图的Log可以看出。效果图如下:
效果图-02
如上图,新增了2个布局文件,垂直方向和水平方向,展示的文字效果和颜色不同。
- 垂直布局文件 activity_life_cycle.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".LifeCycleActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="垂直:"/>
<TextView
android:id="@+id/text_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
android:textColor="@color/colorPrimary"
android:textStyle="bold"
android:text="0" />
</LinearLayout>
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="50dp"
android:layout_marginTop="30dp"
android:padding="16dp"
android:textSize="18sp"
android:text="点一次,显示的数字加1"/>
</LinearLayout>
水平布局文件 activity_life_cycle.xml:
在res文件下创建水平布局的文件夹: layout-land,可以实现水平方向和垂直方向的布局文件展示效果不一样,但文件名称和Activity中引用的View组件必须在布局中都存在且id名也一样。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".LifeCycleActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textSize="16sp"
android:text="横竖屏展示的页面不同"/>
<TextView
android:id="@+id/text_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
android:textColor="@color/colorAccent"
android:textStyle="bold"
android:text="0" />
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:paddingHorizontal="30dp"
android:paddingVertical="20dp"
android:textSize="18sp"
android:text="点一次,显示的数字加1"/>
</LinearLayout>
三、横竖屏切换时,页面数据一致性的保持:
上面的图-02,横竖屏切换时:竖屏时显示的数字默认是0,点击按钮后,展示的数字在逐渐增加。将屏幕转换成横屏时,展示的数据又变为0,是由于屏幕竖屏切换横屏时Activity先销毁再创建横向布局,导致竖屏上的数据丢失。
之前已用过Bundle,如下列代码所示,它作为参数传入onCreate(Bundle)方法:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
覆写父类的onCreate(Bundle)方法时,我们实际是在调用activity超类的onCreate(Bundle)方法,并传入收到的bundle。在超类代码实现里,通过取出保存的视图状态数据, activity的视图层级结构得以重建。
覆盖 onSaveInstanceState(Bundle)方法:将一些数据保存在bundle中,然后在onCreate(Bundle)方法中取回这些数据。屏幕旋转时,我们可以通过此方法来保证屏幕旋转后,屏幕展示的数据与没旋转之前的数据一致。
- 重写父类中的onSaveInstanceState(Bundle)方法
public class LifeCycleActivity extends AppCompatActivity {
...
private int number =0;
private static final String KEY_INDEX = "index";//标记key
...
@Override
protected void onPause() {
...
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
Log.i(TAG, "onSaveInstanceState");
//将旋转前显示的数字进行保存
outState.putInt(KEY_INDEX, number);
}
@Override
protected void onStop() {
...
}
...
}
- Activity布局页面初始化时,进行赋值,首次Bundle 中没有保存数值时,默认为0。
添加的代码如下:初始化页面时,从onCreate(Bundle savedInstanceState)方法 中的savedInstanceState对象中进行查询是否有旋转前保存的数值 如果有就对number进行赋值,没有默认设置mumber =0;
if (savedInstanceState != null) {
number = savedInstanceState.getInt(KEY_INDEX, 0);
text_show.setText(number+"");
}
public class LifeCycleActivity extends AppCompatActivity {
private TextView text_show;
private Button btn_add;
//保存到Bundle中数据的 标记key名
private static final String KEY_INDEX = "index";
private static final String TAG = "LifeCycleActivity";
private int number =0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_life_cycle);
Log.d(TAG, "onCreate() 方法");
text_show = (TextView) findViewById(R.id.text_show);
btn_add = (Button) findViewById(R.id.btn_add);
if (savedInstanceState != null) {
number = savedInstanceState.getInt(KEY_INDEX, 0);
//在控件对象实例化后进行赋值
text_show.setText(number+"");
}
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
number++;
text_show.setText(number+"");
}
});
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
Log.i(TAG, "onSaveInstanceState");
outState.putInt(KEY_INDEX, number);
}
......
}
最后,重新运行代码,查看横竖屏切换后,添加的数据是否保存不变进行展示。
效果图如下:
完整代码如下:
**
* Activity生命周期
* 使用@Override注解,就是要求编译器保证当前子类拥有你要覆盖的方法
*/
public class LifeCycleActivity extends AppCompatActivity {
private TextView text_show;
private Button btn_add;
private static final String KEY_INDEX = "index";//标记key
private static final String TAG = "LifeCycleActivity";
private int number =0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_life_cycle);
Log.d(TAG, "onCreate() 方法");
text_show = (TextView) findViewById(R.id.text_show);
btn_add = (Button) findViewById(R.id.btn_add);
if (savedInstanceState != null) {
number = savedInstanceState.getInt(KEY_INDEX, 0);
text_show.setText(number+"");
}
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
number++;
text_show.setText(number+"");
}
});
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
Log.i(TAG, "onSaveInstanceState");
outState.putInt(KEY_INDEX, number);
}
@Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart() 方法");
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume() 方法");
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause() 方法");
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop() 方法");
}
@Override
public void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart() 方法");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() 方法");
}
}