一、前言
学习Android开发,当然要以基础为重,而Android中尤为基础的就是四大组件——Activity(活动)、Service(服务)、Broadcast Receiver(广播)、Content Provider(内容提供器)。在此以谷歌Android开发者网站的参考文档以及实际代码为切入点,初步学习Activity的生命周期,作为学习的总结。
二、Activity生命周期
1. 小问题
在此,让我们回忆一下Activity的生命周期有哪些代表性的函数?
如果5秒之内还没有答案的话,那么证明基础真的不牢固了。在日常的开发中我们经常要在Activity的生命周期中进行不同的操作,而牢记生命周期,初步掌握Activity的运行流程,是学习Android开发的必经之路,要时刻记住,开发的过程中不要依赖搜索引擎,大部分情况下这会降低开发效率。
想到Activity生命周期,我们会想到,onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy()还有onRestart()
2. 官方Activity生命周期流程图
三、 代码实践
在学习的过程中,如果满足于文档的图片或者文字,那么我们收获到的仅仅是印象,当你要使用的时候,你会想到到哪里查。知识有遗忘曲线,何况这看一眼得来的印象。对此我选择应用在实例中进行验证学习。
在一个Android工程中新建一个Activity,当然,这样描述是笼统的,这对我们的学习没有好处。我们在脑海中更应该把它想象为
1. 在工程目录->app->src->main->java->xxx(包名),新建一个名为TestActivity的Java Class
2. 在工程目录->app->src->main->res->layout,新建一个名为activity_test的Layout resource file
3. 在Activity中继承Activity(AppCompatActivity),并重写onCreate()方法,并添加setContentView(R.layout.activity_test);
4. 修改工程目录->app->src->main->AndroidManifest.xml文件,在标签中添加标签并指定name等属性
以上流程是提醒自己不要忽略工具背后帮开发者所做的工作,在新建的工程中,是存在MainActivity的,所以以下以MainActivity为例,学习Activity的生命周期
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "【生命周期】Activity";
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
}
@Override
protected void onStart() {
Log.d(TAG, "onStart");
super.onStart();
}
@Override
protected void onResume() {
Log.d(TAG, "onResume");
super.onResume();
}
@Override
protected void onPause() {
Log.d(TAG, "onPause");
super.onPause();
}
@Override
protected void onStop() {
Log.d(TAG, "onStop");
super.onStop();
}
@Override
protected void onRestart() {
Log.d(TAG, "onRestart");
super.onRestart();
}
@Override
protected void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
}
}
因为布局无内容,就不贴代码了,还有MainActivity在新工程中默认为启动的Activity,所以也不需要另外startActivity。
- 正常启动
此时Activity进入可见的运行状态 - 点击任务键进入任务列表
此时Activity进入后台不可见状态(即使在任务切换列表中可看到Acvitity的预览图,但是Activity还是进入了后台) - 点击返回当前程序
此时Activity再次进入了可见的运行状态 - 点击电源键息屏
此时Activity还是进入了后台不可见状态 - 点击任务键进入任务列表清除当前应用程序
此时应用被清除,当前Activity会调用onPause和onStop外,还会调用onDestroy方法
四、 进一步思考
似乎在测试的时候都在测试焦点与可见性对生命周期的影响,但是我们忽略了其中一种情况,当前Activity可见但无焦点的情况。
Show Me The Code
4.1. 当另一个透明的Activity启动在本Activity上
在MainActivity中添加一个按钮并添加点击函数(为了效果显著,找了个有内容的布局,点击登陆按钮触发)
Button button = findViewById(R.id.btn_test); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, TestActivity.class)); } });
在colors.xml中添加透明色
<color name="colorTransparent">#00000000</color>
在styles.xml中添加透明的style
<style name="MyTransparent" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@color/colorTransparent</item> <item name="android:windowIsTranslucent">true</item> </style>
在AndroidManifest.xml中设置Activity的Theme
<activity android:name=".TestActivity" android:theme="@style/MyTransparent"/>
修改TestActivity的布局(为了呈现透明效果)
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="200dp" android:layout_height="200dp" android:background="@color/colorGray" android:layout_gravity="center" tools:context=".TestActivity"> </android.support.constraint.ConstraintLayout>
运行
虚拟机运行效果图
点击按钮启动另一个透明的Activity
再看看日志
这种情况MainActivity并没有调用onStop方法
4.2 切换横竖屏
- 打开手机横竖屏开关
- 手机横屏
- 查看日志
当前Activity会被销毁且重建 - 手机恢复竖屏
- 查看日志
发现和步骤3一样,还是依次调用了onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()
总结:手机横竖屏切换会导致Activity销毁重走生命周期
4.3 打开对话框
在当前Activity打开AlertDialog等界面时,虽然遮挡了Activity界面,设置Dialog的Cancelable属性还可使焦点落在对话框上,但是并没有影响到Activity生命周期,在对话框的创建和隐藏过程中,Activity生命周期不变
五、生命周期分析
- onCreate()
使用最多,继承于Activity会默认重写该函数。通常此函数中完成Activity初始化操作如设置布局、初始化布局、绑定事件。 - onStart()
此时Activity还处于不可见状态,在Activity可见前被调用。 - onResume()
在Activity变可见时被调用,执行完该函数后,Activity会请求AMS渲染它所管理的视图,此时Activity处于返回栈的栈顶,并处于运行状态。 - onPause()
系统准备启动或恢复另一个Activity时调用。通常在此函数将一些消耗CPU的资源释放掉,以及保存一些关键数据。 - onStop()
此函数在Activity完全不可见时调用(熄屏、应用后台或者另一个Activity完全覆盖不可见),但是如果新启动的Activity是一个对话框式的Activity(被覆盖的Activity仍可见),此方法不调用。 - onDestroy()
在Activity被销毁前调用,通常在此函数完成内存的释放操作。 - onRestart()
Activity由停止状态重新转变为运行状态前调用。
六、参考资料
- 谷歌官方文档 - Activity部分
- 《Android进阶之光》 —— 刘望舒