1.Activity的四种状态
- Running
一个新的Activity启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。 - Paused
当Activity被另一个透明或者Dialog样式的Activity覆盖时的状态。此时它依然与窗口管理器保持连接,系统继续维护其内部状态,它仍然可见,但它已经失去了焦点,故不可与用户交互。 - Stopped
当Activity不可见时,Activity处于Stopped状态。当Activity处于此状态时,一定要保存当前数据和当前的UI状态,否则一旦Activity退出或关闭时,当前的数据和UI状态就丢失了。 - Killed
Activity被杀掉以后或者被启动以前,处于Killed状态。这是Activity已从Activity堆栈中移除,需要重新启动才可以显示和使用。
4种状态中,Running状态和Paused状态是可见的,Stopped状态和Killed状态时不可见的。
2.Activity的生命周期
图解Activity生命周期
image.pngActivity生命周期分析
public class LifeCycleActivity extends AppCompatActivity {
static final String TAG = "LifeCycleActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_life_cycle);
Log.d(TAG, "onCreate");
}
/**
* 这个函数提供了为我们在某些情况下保存Activity信息的机会,但需要注意的是这个函数不是什么时候都会被调用的
* @param outState
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "onSaveInstanceState");
}
/**
* 这个方法在一个activity被杀死前调用,当该activity在将来某个时刻回来时可以恢复其先前状态
* @param savedInstanceState
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, "onRestoreInstanceState");
}
public void onStart() {
super.onStart();
Log.d(TAG, "onStart");
}
public void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart");
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
}
public void onPause() {
super.onPause();
Log.d(TAG, "onPause");
}
public void onStop() {
super.onStop();
Log.d(TAG, "onStop");
}
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
1.Activity启动
onCreate -> onStart -> onResume
启动.png2.点击Home键回到主界面(Activity不可见)
onPause -> onStop
回到主界面3.当我们再次回到Activity时
onReStart -> onStart -> onResume
再次回到Activity4.当我们退出Activity时
onPause -> onStop -> onDestory
退出Activity时5.横竖屏切换
onPause -> onSaveInstanceState -> onStop -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume
转屏.png那么如何防止横竖屏切换时Activity重建呢?
有一种简单的办法只要在清单文件中为Activity需要配置configChange参数就可以解决这个问题
android:configChanges="orientation|screenSize"
我们可以实现检查当前设备方向
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
那么是不是用了“android:configChanges”就万事大吉了,显然不是的。
Android Developers里说:
Note: Handling the configuration change yourself can make it much more difficult to use alternative resources, because the system does not automatically apply them for you. This technique should be considered a last resort when you must avoid restarts due to a configuration change and is not recommended for most applications.
自行处理配置变更可能导致备用资源的使用更为困难,因为系统不会为您自动应用这些资源。 只能在您必须避免 Activity 因配置变更而重启这一万般无奈的情况下,才考虑采用自行处理配置变更这种方法,而且对于大多数应用并不建议使用此方法。
Not only because there are other configuration changes that you cannot prevent from restarting your application, but also because you should handle events such as when the user leaves your application and it gets destroyed before the user returns to it.
其实不止屏幕旋转。还存在其他一些无法禁止重启应用的配置变更,这些需要我们手动处理,例如用户离开应用(突然接到个电话等等),当用户再次回来的时候,之前的系统由于资源紧张而销毁了应用进程。
Android任务栈
- 一个应用程序一般都是由多个Activity组成的,任务栈就是用来记录打开的Activity。
- 任务栈(task stack)也可以叫返回栈(back stack),具有后进先出的特性,栈中Activity的顺序就按照它们被打开的顺序依次存放的。
- 一个应用程序一被开启系统就给他分配一个任务栈,当所有的Activity都退出的时候,任务栈就清空了
- 一个App中可能不止一个任务栈,某些特殊情况下,单独一个Actvity可以独享一个任务栈
- 一个Task中的Activity可以来自不同的App,同一个App的Activity也可能不在一个Task中。
Android启动模式
为什么需要启动模式
当我们多次启动同一个Activity时,系统会创建多个实例,并把它们按照先进后出的原则一一放入任务栈中,当我们按back键时,就会有一个activity从任务栈顶移除,重复下去,直到任务栈为空,系统就会回收这个任务栈。但是这样以来,系统多次启动同一个Activity时就会重复创建多个实例,这种做法显然不合理,为了能够优化这个问题,Android提供四种启动模式来修改系统这一默认行为。
Activity的四种启动模式
- standard
标准模式,每次都新建一个实例对象。默认模式
- singleTop
如果在任务栈顶发现了相同的实例则重用,否则新建并压入栈顶。
- singleTask
如果在任务栈中发现了相同的实例,将其上面的任务终止并移除,重用该实例。否则新建实例并入栈
- singleInstance
允许不同应用,进程线程等共用一个实例,无论从何应用调用该实例都重用
如有错误和遗漏,欢迎指正
网友评论