写点什么

Activity 生命周期详解,android 游戏开发实践指南

用户头像
Android架构
关注
发布于: 10 小时前

2、AndroidManifest.xml


3、FirstActivity


4、SecondActivity


5、ThirdActivity


6、FourActivity


7、FiveActivity




以实际案例来详细了解 Activity 的声明周期。


问题一:Activity A 启动另一个 Activity B 会回调哪些方法?如果 Activity B 是完全透明呢?如果启动的是一个 Dialog 呢?


========================================================================


  • A 启动 B:A 的 onPause() -->B 的 onCreate()-->onStart()-->onResume()-->A 的 onStop()

  • A 启动 B,B 完全透明:A 的 onPause() -->B 的 onCreate()-->onStart()-->onResume()

  • A 界面启动一个 dialog:如果是单纯的一个 dialog,并不调用生命周期,如果启动的是一个以 dialog 形式展示的 activity,同上。


Demo 逻辑介绍:


FirstActivity:主 Activity


1、启动 SecondActivity:普通的 Activity


A 启动 B:A 的 onPause() -->B 的 onCreate()-->onStart()-->onResume()-->A 的 onStop()


问题:A 的生命周期为什么会先调用 onPause(),在 B 完全展示后再去调用 A 的 onStop()方法,为什么要这样设计?


答:onPause 的调用是“Another activity comes in front of the activity”,即另一个 activity 跑到前台来的时候,前一个 activity 的 onPause 方法会被调用。


onStop 的调用是“The activity is no longer visible”,也就是完全不可见的时候调用的,这个完全不可见真的就是指视觉上的完全看不到而已,无论是按 home 键返回桌面,还是启动另一 activity 把原 activity 完全遮住,都会调用 onStop。但是当启动的 activity 是透明的时候,原 activity 只会进入 onPause 状态,而不会走到 onStop 状态,因为原 acitivity 还是可见的,虽然逻辑上被遮住了,但是视觉上确实是可见的,这一点要注意。


2、启动 ThirdActivity:完全透明的 Activity


A 启动 B,B 完全透明:A 的 onPause() -->B 的 onCreate()-->onStart()-->onResume()


3、启动 FourActivity:以 Dialog 形式展示的 Activity


A 启动 B,B 以 Dialog 形式展示:A 的 onPause() -->B 的 onCreate()-->onStart()-->onResume()


4、启动一个 Dialog


A 界面启动一个 dialog:如果是单纯的一个 dialog,并不调用生命周期


问题二:谈谈 onSaveInstanceState()方法?何时会调用?


====================================


  • a.出现时机:异常 情况下 Activity 重建,非用户主动去销毁

  • b.系统异常终止时,调用 onSavaInstanceState 来保存状态。该方法调用在 onStop 之前,但和 onPause 没有时序关系。

  • c.Activity 被重新创建时,调用 onRestoreInstanceState(该方法在 onStart 之后),并将 onSavaInstanceState 保存的 Bundle 对象作为参数传到 onRestoreInstanceState 与 onCreate 方法。


5、启动 FiveActivity


在该界面设置一个按钮(点击触发空指针异常),点击按钮界面崩溃退出。


结果:在此种情况下不会触发 onSaveInstanceState()方法!


另外:横竖屏切换也不会触发 onSaveInstanceState()方法! 但是会触发 onRestoreInstanceState()方法。


[activity 中的 onSaveInstanceState 方法的调用时机](


)?在该文章中所列举的几种方法都尝试过了,但是都没有触发 onSaveInstanceState()方法。


问题三:横竖屏切换时,Activity 的声明周期如何变化


============================


如果不做任何配置:


会销毁当前 Activity 然后在新创建一个,生命周期如下:


onPause() --> onStop() --> onDestory() --> onCreate()-->onStart()-->onResume()


Adnroid 3.2 以后的 SDK 需要设置: android:configChanges="orientation|keyboardHidden|screenSize"


manifest 中为相应的 Activity 设置 android:configChanges 属性即可


Andorid 3.2 以前的 SDK 可以使用如下配置


android:configChanges="orientation|keyboardHidden"


而 Adnroid 3.2 以后的 SDK 必须添加一个 screenSize 属性,具体如下


android:configChanges="keyboardHidden|orientation|screenSize"


或者


android:configChanges="orientation|screenSize"


对 android:configChanges 的总结


1、不设置 Activity 的 android:configChanges 时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次(在三星 4.0 设备上切横屏和竖屏都是执行一次,而并非这里说的有执行两次的情况);


2、设置 Activity 的 android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次;


3、设置 Activity 的 android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行 onConfigurationChanged 方法。


注:上述描述是在 Android3.2 以前,如果缺少了 keyboardHidden 选项,不能防止 Activity 的销毁重启,也就不能执行 onConfigurationChanged 方法了。在 3.2 之后,必须加上 screenSize 属性才可以屏蔽调用 Activity 的生命周期(一些设备上可以不需要 keyboardHidden,只要 screenSize 就可以了,保守起见还是继续保留 keyboardHidden 吧)。


源码展示:


=====


1、style.xml




<resources>


<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">


<item name="colorPrimary">@color/colorPrimary</item>


<item name="colorPrimaryDark">@color/colorPrimaryDark</item>


<item name="colorAccent">@color/colorAccent</item>


</style>


<style name="BtnCommon">


<item name="android:layout_width">match_parent</item>


<item name="android:layout_height">60dp</item>


<item name="android:textAllCaps">false</item>


<item name="android:textSize">16sp</item>


</style>


<style name="dialogStyle" parent="Theme.AppCompat.Light.Dialog">


<item name="windowNoTitle">true</item>


<item name="android:windowContentOverlay">@null</item>


<item name="android:windowIsFloating">true</item>


<item name="android:windowFrame">@null</item>


<item name="android:backgroundDimEnabled">true</item>


</style>


<style name="TranslucentTheme" parent="Theme.AppCompat.Light.Dialog">


<item name="android:windowBackground">@android:color/transparent</item>


<item name="android:colorBackgroundCacheHint">@null</item>


<item name="android:windowIsTranslucent">true</item>


<item name="android:windowAnimationStyle">@android:style/Animation</item>


<item name="android:windowNoTitle">true</item>


<item name="android:windowContentOverlay">@null</item>


</style>


</resources>


2、AndroidManifest.xml




<activity android:name=".lifecycle.FirstActivity" />


<activity android:name=".lifecycle.SecondActivity" />


<activity


android:name=".lifecycle.ThirdActivity"


android:theme="@style/TranslucentTheme" />


<activity


android:name=".lifecycle.FourActivity"


android:theme="@style/dialogStyle" />


<activity


android:name=".lifecycle.FiveActivity"


android:configChanges="orientation|keyboardHidden|screenSize" />


3、FirstActivity




public class FirstActivity extends AppCompatActivity {


@Override


protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


setContentView(R.layout.activity_first);


ButterKnife.bind(this);


LogUtils.e("onCreate");


}


@OnClick({R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4, R.id.btn5})


public void onViewClicked(View view) {


switch (view.getId()) {


case R.id.btn1://1、启动 SecondActivity:普通的 Activity


startActivity(new Intent(this, SecondActivity.class));


break;


case R.id.btn2://2、启动 ThirdActivity:完全透明的 Activity


startActivity(new Intent(this, ThirdActivity.class));


break;


case R.id.btn3://3、启动 FourActivity:以 Dialog 形式展示的 Activity


startActivity(new Intent(this, FourActivity.class));


break;


case R.id.btn4://4、启动一个 Dialog


new AlertDialog.Builder(this).setIcon(R.mipmap.ic_launcher).setTitle("最普通 dialog")


.setMessage("我是最简单的 dialog").setPositiveButton("确定(积极)", new DialogInterface.OnClickListener() {


@Override


public void onClick(DialogInterface dialogInterface, int i) {


Toast.makeText(FirstActivity.this, "确定按钮", Toast.LENGTH_LONG).show();


}


}).setNegativeButton("取消(消极)", new DialogInterface.OnClickListener() {


@Override


public void onClick(DialogInterface dialogInterface, int i) {


Toast.makeText(FirstActivity.this, "关闭按钮", Toast.LENGTH_LONG).show();


dialogInterface.dismiss();


}


}).create().show();


break;


case R.id.btn5://5、启动 FiveActivity: 在该界面设置一个按钮,点击按钮界面崩溃退出。


startActivity(new Intent(this, FiveActivity.class));


break;


}


}


@Override


protected void onStart() {


super.onStart();


LogUtils.e("onStart");


}


@Override


protected void onResume() {


super.onResume();


LogUtils.e("onResume");


}


@Override


protected void onPause() {


super.onPause();


LogUtils.e("onPause");


}


@Override


protected void onStop() {


super.onStop();


LogUtils.e("onStop");


}


@Override


protected void onRestart() {


super.onRestart();


LogUtils.e("onRestart");


}


@Override


protected void onDestroy() {


super.onDestroy();


LogUtils.e("onDestroy");


}


@Overri


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


de


public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {


super.onSaveInstanceState(outState, outPersistentState);


LogUtils.e("onSaveInstanceState");


}


@Override


protected void onRestoreInstanceState(Bundle savedInstanceState) {


super.onRestoreInstanceState(savedInstanceState);


LogUtils.e("onRestoreInstanceState");


}


}


<?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"


tools:context="com.gs.sumok2.lifecycle.FirstActivity"


android:orientation="vertical">


<Button


android:id="@+id/btn1"


style="@style/BtnCommon"


android:text="SecondActivity" />


<Button


android:id="@+id/btn2"


style="@style/BtnCommon"


android:text="ThirdActivity" />


<Button


android:id="@+id/btn3"


style="@style/BtnCommon"


android:text="FourActivity" />


<Button


android:id="@+id/btn4"


style="@style/BtnCommon"


android:text="Dialog" />


<Button


android:id="@+id/btn5"


style="@style/BtnCommon"


android:text="FiveActivity" />


</LinearLayout>


4、SecondActivity




public class SecondActivity extends AppCompatActivity {


@Override


protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


setContentView(R.layout.activity_second);


LogUtils.e("onCreate");


}


@Override


protected void onStart() {


super.onStart();


LogUtils.e("onStart");


}


@Override


protected void onResume() {


super.onResume();


LogUtils.e("onResume");


}


@Override


protected void onPause() {


super.onPause();


LogUtils.e("onPause");


}


@Override


protected void onStop() {


super.onStop();


LogUtils.e("onStop");


}


@Override


protected void onRestart() {


super.onRestart();


LogUtils.e("onRestart");


}


@Override


protected void onDestroy() {


super.onDestroy();


LogUtils.e("onDestroy");


}


}


<?xml version="1.0" encoding="utf-8"?>


<android.support.constraint.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:layout_width="match_parent"


android:layout_height="match_parent"


tools:context="com.gs.sumok2.lifecycle.SecondActivity">

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Activity生命周期详解,android游戏开发实践指南