Android中 Activity生命周期及横竖屏切换时数据一致性的保持

研究: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() 方法");
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值