Android Activity生命周期整理
2016-02-05 16:22
489 查看
最近,开始学习android官网提供的training 官方文档。比起一般学习教材,官网上的内容,给我最大的感受是,这更像是软件设计的艺术。它不仅仅讲每个知识点具体应该如何做,能达到效果,另外一点非常重要的内容是:对应每个知识点,我们需要注意什么,这里为什么不能写具体的coding,在那就能写了。废话不多说,开始翻译、记录、学习。
这是Android启动应用时,activity将要走过的路线。和之前我学到的Activity图有所出路。
这两张图都描述了activity的行走路线,我个人更喜欢第一张图。第一张图的描述,类似于金字塔型。这非常形象地描述了Activity从onCreate()开始是如何一步一步走向顶端的Resumed。由图也能看出,一个activity经过onCreate()以及onStart()后,倘若activity始终处于运行状态,它将停留在Resumed状态下。接着,图片又描述了Paused状态以及Stopped状态。它们在不同的情况下,又能回到Resumed状态,最后便是金字塔的另外一端,Destroyed。这也就意味着Activity最终将释放所有资源,从内存中退出。
在用户转去接听电话时或者操作其他APP时,你的编写APP不能崩溃。(对应的是哪些状态函数需要修改呢?)
当用户并没有想要使用它,不要消费系统资源。
当用户短暂离开APP时,如有必要,要能够把当前用户的数据记录下来。
当屏幕切换竖屏横屏时,不要导致APP崩溃以及用户数据的丢失。
用户操作手机的过程,都会相应的调用状态函数,因此,我们应该清楚这些注意点,对应的都是哪些状态函数。以及写该状态函数时,需要注意的点。
在上图展示的六个状态,其中三个是属于静态的,而另外三个是瞬态的(将直接跳转到下一状态。)。静态的便是:Resumed、Paused、Stopped,这三个状态能长时间存在。
Resumed:
在这个状态下,activity运行在前台,用户能够做任何操作。
Paused:
只有当前activity被另外一个activity部分遮住,或者另外一个activity为半透明,总之不能被全部遮住,才会跳转到这个状态下。值得注意的是:在这个状态下是不能接收用户输入操作并且不能执行任何用户操作。
Stopped:
在这个状态下,当前activity被全部遮住,即对用户不可见,但是它还在后台俏俏的待命。当activity 停止时,当前activity实例以及状态信息,诸如成员变量等都保留在内存中,但不能执行任何用户操作。
这便是activity最基本的生命周期。接下来,将介绍每个状态对应具体的行为。
想了解activity创建后,所有状态是如何依次执行的,只要重写各种状态回调函数即可。这里列出最常用的onCreat()方法的构建。
onCreate方法是瞬态的,一旦执行完所有的初始化代码,便立即执行onStart方法,onResume方法,到达Resumed状态。用户操作均在此状态下完成。
当用户正常使用APP时,有时候便会发生切换视图组件,导致当前activity暂停的情况。只要当前activity的一部分视图能被用户看见,但用户的操作不聚焦在当前activity上,便会发生状态转移。
一旦activity从paused状态回到resumed状态,就会调用onResume方法。当用户调用onPause方法后,很大的概率将要导致用户离开APP,这也就暗示着会相继发生onStop方法。因此,我们通常在onPause()方法中需注意几点:
提交没有保存的数据,尤其是用户希望在离开时能够自动保存的数据。(草稿邮件等)
释放系统资源,诸如:广播,传感处理器(GPS等),或者其他任何可能影响电池寿命的系统资源且用户使用不到的。
停止动画或者其他一些消耗CPU的活动。
举个例子:当我们使用相机时,在onPause()方法中记得释放它。
但一般情况下,也并非保存所有的用户数据,除非用户是希望当离开APP时,有自动保存的功能,草稿箱适合这样的情况下使用。而且,我们应该尽量避免保存数据的操作时间过程,如需要写入数据库等操作,这会影响用户切换到其他activity的用户体验。尽量将这些繁杂的操作在onStop()方法中执行。总之,在onPause()中,尽量简化代码,以获得更快的转移效果。
Note: 当activity进入paused状态后,它之前所初始化的组件信息是存储在内存中的,并不会消失,因此也无需在onResume()方法中重新进行初始化。
正如前面代码所示,如果你在onPause方法中,释放了一些系统资源,那么一旦用户回到activity就需要相应的初始化释放掉的资源。其次,初始化之前只在onResume方法中初始化的资源。
当用户打开最近使用的APP窗口,并且转到另外一个APP时,当前的activity将会调用onStop()方法,进入Stopped状态,当用户再次返回时,会回调onRestart()方法,重新进入started状态以及Resumed状态。
当用户在当前界面启动另外一个新的activity后,当前activity将进入stopped状态,当用户按住返回按钮后,重新回调onRestart()方法。
当用户使用当前app时,有电话接入,也会进入Stopped状态。
这里同样需要注意的一点是:如同进入Paused状态一样,系统还会保留当前activity实例在我们的内存中。因此,也可以不用重写onStop()和onRestart()方法。对于绝大多数简单的应用,只需要在activity进入stopped状态之前,重写onPause()方法,来关闭一些正在执行的动作,释放系统资源即可。
还需要注意一点的是:有时候系统由于内存资源使用紧张的情况下,会莫名其妙的直接kill掉你的app程序,这时候它是不会调用onDestroy()方法的,因此,在onStop中,如果APP涉及一些大资源,如数据库的读写操作的使用时,建议在onStop方法中,保存用户数据并关掉这些资源,避免内存泄漏。
如用户在编辑内容时,onStop方法中保存这些内容:
记得,在onRestart方法中,重新获得这些数据即可。但是否所有的用户数据需要保存呢?不然,视图组件的状态,系统其实会自动记录在内存中,如在editText中,编写的用户数据,完全不需要保存,当用户从stopped状态回到resumed状态后,editText里的内容由系统自动调用。甚至在destroyed状态下,这些数据依然留存。因此,对于我们来讲,注意那些非视图组件的信息的留存即可。
在官方文档中,它其实并不提倡使用onRestart方法,除非一些应用是确定不会进入destroyed状态,只会停留在stopped状态。但为了以防万一,还是建议使用onStart方法,并且在onStart方法中,要注意当前的系统环境是否支持某些初始化操作。如:
最后还需注意的一点是:在onDestroy()方法中,是最后释放所有系统资源的机会,切忌别让app内存泄漏了。o(︶︿︶)o
用户操作返回按钮后。
在程序中调用finish方法。
app进入stopped状态后,用户长时间并没有唤醒app,系统清理内存时,自动关闭它。
当然,并非所有的程序APP如我们所想,能顺利结束,有很多种情况让它意外退出,因此,为了防止意外退出的发生,系统提供了一种机制来保存activity的实例,这种机制便是 通过bundle绑定“instance state”,以键值对的方式保存在bundle对象中。当程序app启动时,自动加载系统的实例状态,呈现在用户面前。前面提到的editText中的文本信息的留存,便是最好的例证。
可惜,系统只能保存有限的信息,编写程序时,有很多用户数据是并非由系统来完成管理的。因此,如果想要保存额外的信息,需要借助onSaveInstanceState()方法来实现。
由图可以看出,在进入Destroyed之前,该方法自动执行,我们只要在这里记录一些用户信息,传给bundle即可。当下次app重启时,在onCreate方法和onRestoreInstanceState方法中,都能够重新加载信息。有两个地方供我们提取出之前维护的信息,选择其中一个方法即可。
来个例子:
重新加载用户保存的信息:
这里需要注意的一点是:savedInstanceState判空的细节,因为程序很有可能正常退出,因此savedInstanceState,在app创建一个新的实例时,定为空。这也验证了,只有当程序意外退出时,才会调用onSaveInstanceState方法。
当然,我们也可以选择更加方便的方法,无需判空,重写onRestoreInstanceState方法即可:
分享结束、fighting!o(∩_∩)o
理解activity生命周期函数
这是Android启动应用时,activity将要走过的路线。和之前我学到的Activity图有所出路。
这两张图都描述了activity的行走路线,我个人更喜欢第一张图。第一张图的描述,类似于金字塔型。这非常形象地描述了Activity从onCreate()开始是如何一步一步走向顶端的Resumed。由图也能看出,一个activity经过onCreate()以及onStart()后,倘若activity始终处于运行状态,它将停留在Resumed状态下。接着,图片又描述了Paused状态以及Stopped状态。它们在不同的情况下,又能回到Resumed状态,最后便是金字塔的另外一端,Destroyed。这也就意味着Activity最终将释放所有资源,从内存中退出。
官方文档中在此刻提出编写APP四个要求:
在用户转去接听电话时或者操作其他APP时,你的编写APP不能崩溃。(对应的是哪些状态函数需要修改呢?)当用户并没有想要使用它,不要消费系统资源。
当用户短暂离开APP时,如有必要,要能够把当前用户的数据记录下来。
当屏幕切换竖屏横屏时,不要导致APP崩溃以及用户数据的丢失。
用户操作手机的过程,都会相应的调用状态函数,因此,我们应该清楚这些注意点,对应的都是哪些状态函数。以及写该状态函数时,需要注意的点。
在上图展示的六个状态,其中三个是属于静态的,而另外三个是瞬态的(将直接跳转到下一状态。)。静态的便是:Resumed、Paused、Stopped,这三个状态能长时间存在。
Resumed:
在这个状态下,activity运行在前台,用户能够做任何操作。
Paused:
只有当前activity被另外一个activity部分遮住,或者另外一个activity为半透明,总之不能被全部遮住,才会跳转到这个状态下。值得注意的是:在这个状态下是不能接收用户输入操作并且不能执行任何用户操作。
Stopped:
在这个状态下,当前activity被全部遮住,即对用户不可见,但是它还在后台俏俏的待命。当activity 停止时,当前activity实例以及状态信息,诸如成员变量等都保留在内存中,但不能执行任何用户操作。
这便是activity最基本的生命周期。接下来,将介绍每个状态对应具体的行为。
实战一发
想了解activity创建后,所有状态是如何依次执行的,只要重写各种状态回调函数即可。这里列出最常用的onCreat()方法的构建。TextView mTextView; // Member variable for text view in the layout
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the user interface layout for this Activity
// The layout file is defined in the project res/layout/main_activity.xml file
setContentView(R.layout.main_activity);
// Initialize member TextView so we can manipulate it later
mTextView = (TextView) findViewById(R.id.text_message);
Log.d("debug","oncreate() callback......");
// Make sure we're running on Honeycomb or higher to use ActionBar APIs
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// For the main activity, make sure the app icon in the action bar
// does not behave as a button
ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
}
}
Created状态总结:
onCreate方法是android程序初始化最先执行的回调方法,因此,所有的界面初始化工作,以及任何APP所需的资源初始化工作要在该方法下完成。onCreate方法是瞬态的,一旦执行完所有的初始化代码,便立即执行onStart方法,onResume方法,到达Resumed状态。用户操作均在此状态下完成。
Resumed&&Paused状态总结:
当用户正常使用APP时,有时候便会发生切换视图组件,导致当前activity暂停的情况。只要当前activity的一部分视图能被用户看见,但用户的操作不聚焦在当前activity上,便会发生状态转移。一旦activity从paused状态回到resumed状态,就会调用onResume方法。当用户调用onPause方法后,很大的概率将要导致用户离开APP,这也就暗示着会相继发生onStop方法。因此,我们通常在onPause()方法中需注意几点:
提交没有保存的数据,尤其是用户希望在离开时能够自动保存的数据。(草稿邮件等)
释放系统资源,诸如:广播,传感处理器(GPS等),或者其他任何可能影响电池寿命的系统资源且用户使用不到的。
停止动画或者其他一些消耗CPU的活动。
举个例子:当我们使用相机时,在onPause()方法中记得释放它。
@Override
public void onPause() {
super.onPause(); // Always call the superclass method first
// Release the Camera because we don't need it when paused
// and other activities might need to use it.
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
但一般情况下,也并非保存所有的用户数据,除非用户是希望当离开APP时,有自动保存的功能,草稿箱适合这样的情况下使用。而且,我们应该尽量避免保存数据的操作时间过程,如需要写入数据库等操作,这会影响用户切换到其他activity的用户体验。尽量将这些繁杂的操作在onStop()方法中执行。总之,在onPause()中,尽量简化代码,以获得更快的转移效果。
Note: 当activity进入paused状态后,它之前所初始化的组件信息是存储在内存中的,并不会消失,因此也无需在onResume()方法中重新进行初始化。
正如前面代码所示,如果你在onPause方法中,释放了一些系统资源,那么一旦用户回到activity就需要相应的初始化释放掉的资源。其次,初始化之前只在onResume方法中初始化的资源。
@Override
public void onResume() {
super.onResume(); // Always call the superclass method first
// Get the Camera instance as the activity achieves full user focus
if (mCamera == null) {
initializeCamera(); // Local method to handle camera init
}
}
Stopped&&Started状态总结:
在我们的程序中,恰当的停止以及重启我们的程序是必要的。设计软件时,需给用户一种完整的app体验。Stopped发生的场景:当用户打开最近使用的APP窗口,并且转到另外一个APP时,当前的activity将会调用onStop()方法,进入Stopped状态,当用户再次返回时,会回调onRestart()方法,重新进入started状态以及Resumed状态。
当用户在当前界面启动另外一个新的activity后,当前activity将进入stopped状态,当用户按住返回按钮后,重新回调onRestart()方法。
当用户使用当前app时,有电话接入,也会进入Stopped状态。
这里同样需要注意的一点是:如同进入Paused状态一样,系统还会保留当前activity实例在我们的内存中。因此,也可以不用重写onStop()和onRestart()方法。对于绝大多数简单的应用,只需要在activity进入stopped状态之前,重写onPause()方法,来关闭一些正在执行的动作,释放系统资源即可。
还需要注意一点的是:有时候系统由于内存资源使用紧张的情况下,会莫名其妙的直接kill掉你的app程序,这时候它是不会调用onDestroy()方法的,因此,在onStop中,如果APP涉及一些大资源,如数据库的读写操作的使用时,建议在onStop方法中,保存用户数据并关掉这些资源,避免内存泄漏。
如用户在编辑内容时,onStop方法中保存这些内容:
@Override
protected void onStop() {
super.onStop(); // Always call the superclass method first
// Save the note's current draft, because the activity is stopping
// and we want to be sure the current note progress isn't lost.
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
getContentResolver().update(
mUri,// The URI for the note to update.
values, // The map of column names and new values to apply to them.
null,// No SELECT criteria are used.
null // No WHERE columns are used.
);
}
记得,在onRestart方法中,重新获得这些数据即可。但是否所有的用户数据需要保存呢?不然,视图组件的状态,系统其实会自动记录在内存中,如在editText中,编写的用户数据,完全不需要保存,当用户从stopped状态回到resumed状态后,editText里的内容由系统自动调用。甚至在destroyed状态下,这些数据依然留存。因此,对于我们来讲,注意那些非视图组件的信息的留存即可。
在官方文档中,它其实并不提倡使用onRestart方法,除非一些应用是确定不会进入destroyed状态,只会停留在stopped状态。但为了以防万一,还是建议使用onStart方法,并且在onStart方法中,要注意当前的系统环境是否支持某些初始化操作。如:
@Override
protected void onStart() {
super.onStart(); // Always call the superclass method first
// The activity is either being restarted or started for the first time
// so this is where we should make sure that GPS is enabled
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsEnabled) {
// Create a dialog here that requests the user to enable GPS, and use an intent
// with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action
// to take the user to the Settings screen to enable GPS when they click "OK"
}
}
@Override
protected void onRestart() {
super.onRestart(); // Always call the superclass method first
// Activity being restarted from stopped state
}
最后还需注意的一点是:在onDestroy()方法中,是最后释放所有系统资源的机会,切忌别让app内存泄漏了。o(︶︿︶)o
Destroyed状态总结:
Destroyed发生的场景:用户操作返回按钮后。
在程序中调用finish方法。
app进入stopped状态后,用户长时间并没有唤醒app,系统清理内存时,自动关闭它。
当然,并非所有的程序APP如我们所想,能顺利结束,有很多种情况让它意外退出,因此,为了防止意外退出的发生,系统提供了一种机制来保存activity的实例,这种机制便是 通过bundle绑定“instance state”,以键值对的方式保存在bundle对象中。当程序app启动时,自动加载系统的实例状态,呈现在用户面前。前面提到的editText中的文本信息的留存,便是最好的例证。
可惜,系统只能保存有限的信息,编写程序时,有很多用户数据是并非由系统来完成管理的。因此,如果想要保存额外的信息,需要借助onSaveInstanceState()方法来实现。
由图可以看出,在进入Destroyed之前,该方法自动执行,我们只要在这里记录一些用户信息,传给bundle即可。当下次app重启时,在onCreate方法和onRestoreInstanceState方法中,都能够重新加载信息。有两个地方供我们提取出之前维护的信息,选择其中一个方法即可。
来个例子:
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
重新加载用户保存的信息:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}
这里需要注意的一点是:savedInstanceState判空的细节,因为程序很有可能正常退出,因此savedInstanceState,在app创建一个新的实例时,定为空。这也验证了,只有当程序意外退出时,才会调用onSaveInstanceState方法。
当然,我们也可以选择更加方便的方法,无需判空,重写onRestoreInstanceState方法即可:
public void onRestoreInstanceState(Bundle savedInstanceState) { // Always call the superclass so it can restore the view hierarchy super.onRestoreInstanceState(savedInstanceState); // Restore state members from saved instance mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); }
分享结束、fighting!o(∩_∩)o
相关文章推荐
- Plugin is too old, please update to a more recent version, or set ANDROID_DAILY_OVERRIDE envrinment
- Android 文件存储
- Activity在异常情况下的生命周期——Android开发艺术探索笔记
- android:windowSoftInputMode属性详解
- android不让程序显示在最近程序列表中
- 监听listivew滚动距离最优方案
- Android ADT安装技巧其常见错误处理
- Android 耳机插拔流程源码跟踪浅析
- android的armeabi和armeabi-v7a
- android snackbar 使用
- android prop文件解析过程
- Android6.0的Looper源码分析(1)
- Android- 友盟社会化分享【5.0版本集成文档】
- android底部导航的实现调查
- Android中实现异步任务机制的方式:Handler、AsyncTask
- Android开发笔记(五十七)录像录音与播放
- Android系统编译脚本理解
- Android APK反编译详解
- android 用java动态设置布局(增添删除修改布局)
- android 入门 003 (点击事件)