转自:http://blog.sina.com.cn/s/blog_5ffeae360100ekoo.html~type=v5_one&label=rela_prevarticle
在AndroidSDK发布的官方文档里,实际上已经对Activity所包含的各个重要状态的概念和相互之间转换机制作了较为详细的描述,但梨子的滋味
总是自己尝了才能体会的深刻,笔者就在开发一些应用过程中出现过奇怪的错误,后来经过确定发现是由于没有对Activity状态转换的一些细节理解到位,
从而导致应用本身的一些运行状态被打乱而出现各种错误。因此笔者找个时间特地基于AndroidSDK的Activity描述(AndroidSDK路径
/docs/reference/android/app/Activity.html)做了一些实验,目的是搞清楚Activity各个重要状态的转换
机制。
在做实验前,先依照官方文档的介绍理清一些重要状态的概念,笔者会依照自己开发的经验和理解加上一些解释,如果大家觉得有疑问和待商榷的地方也可以提出来探讨。
Android针对Activity的管理使用的是栈,就是说某一个时刻只有一个Activity处在栈顶,当这个Activity被销毁后,下面的
Activity才有可能浮到栈顶,或者有一个新的Activity被创建出来,则旧的Activity就被压栈沉下去了。从这里我们可以看出
Android似乎是依照一种层次管理所有的Activity的,为什么这么做,个人觉得原因在于Android对Activity的作用定位很重要的一
点是考虑其管理与用户交互的作用,而谈到交互,首要的就是界面了,因此Activity是直接涉及到与用户交互的界面处理的,而任意时刻与用户处于交互状
态的界面只能有一个,所以Android针对Activity的管理采用了具有层次感的栈的数据结构,理解这一点对于Activity一些状态转换的细节
处理非常重要。
依据这种基于界面层次性的理解,官方文档主要提了两点:
1. 只有处于栈顶的Activity一定是出于运行状态的。当启动一个新的Activity时,系统会将它置于栈
顶,同时使其运行,这个时候先前处于栈顶的Activity则被压栈,只有当栈顶的Activity退出时才
可能重新处于栈顶。
2.一个Activity总的来说拥有四种状态,分别是
1)激活(运行)状态:
此时它一定是在屏幕的最前端的,对应Activity栈来说,它是在栈顶的;
2)暂停状态:此时它在屏幕上仍然是可见的,但是失去了焦点。这种情况会发生在当有一个不会占
满整个屏幕或者拥有透明属性的Activity启动并获得了屏幕焦点时。一个暂停状态的Activity还
是存活的(alive),它仍然维持着自己的各个内部状态和成员信息,仍然和window manager保持
连接,但是系统可能会在手机内存极低的情况下杀掉该Activity;
3)终止状态:此时这个Activity在屏幕上完全不可见,它已经被其他的Activity挡住了。这时它维
持着自己的各个内部状态和成员信息,但是由于用户已完全看不见它,其window也会被隐藏掉,
也就是说window manager不再管理其window信息了。停止状态下的Activity会经常由于手机的内
存征用问题被系统杀掉。
4)当Activity被暂停或者终止时,系统可以把它从内存中清除,这个过程也许会提示用户是否要结
束该Activity,也许只会简单地杀掉其进程。当这个Activity重新被用户调出来显示在界面上
时,用户自己必须保证Activity能够完全恢复先前维护的内部状态信息,以使其回到Activity内
部所处先前的状态,以笔者的经验这种情况如果处理不好很容易出现问题。
这第二点实际上依据界面层次考虑就是3种情况:
a.active/running:
此时Activity管理的界面可见,且直接面对和用户的交互;
b.pause:
此时Activity管理的界面可见,但处于后端,类似变成了背景;
c.stop: 此时Activity管理的界面完全不可见。
澄清了上述重要的概念之后,再来看需要研究的Activity具体的函数,很自然可以知道最重要的函数一定就是针对上面三种情况加上Activity自身创建和消毁所涉及到的几个函数了:
public
class Activity extends ApplicationContext {
protected void onCreate(Bundle savedInstanceState);
protected void
onStart();
protected void onRestart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestroy();
}
笔者对这几个函数做了测试实验,以此研究不同状态间的转换,和这几个重要函数的调用顺序,实验非常简单,两个Activity之间的跳
转:Activity1的界面上只有一个按钮,点击后转到到Activity2上,Activity2上同样一个按钮,点击后跳到Activity1上。
我将上述的函数均打上log,便于观察,同时为了过滤其他的log,使用了Error级别,纯粹是为了方便显示。
大致代码如下:
----------------------------------------------------------------------------------------------
public
class ALStudyActivity extends Activity {
private String LOG_TAG =
"ALStudyActivity";
@Override
public void
onCreate(Bundle savedInstanceState) {
Log.e(LOG_TAG,"onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button01 = (Button)findViewById(R.id.Button01);
button01.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
Intent it = new
Intent(ALStudyActivity.this,NewActivity.class);
startActivity(it);
}
});
}
@Override
protected void onDestroy() {
Log.e(LOG_TAG,"onDestroy");
super.onDestroy();
}
.... //其他几个测试函数,不再列出
}
public
class NewActivity extends Activity {
private
String LOG_TAG = "NewActivity";
@Override
public void
onCreate(Bundle savedInstanceState) {
Log.e(LOG_TAG,"onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
Button button02 = (Button)findViewById(R.id.Button02);
button02.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
Intent it = new
Intent(NewActivity.this,ALStudyActivity.class);
startActivity(it);
}
});
}
... //省略,同上
}
----------------------------------------------------------------------------------------------
这里ALStudyActivity对应Activity1,
NewActivity对应Activity2
实验1.
Activity1->按手机(模拟器)Back键退出
输出结果:
实验1
显示了Activity在正常情况下从正常到退出的全部情形。 onDestory只有在Activity真正退出时才会被调用。
实验2. Activity1->手机Home键回主界面
输出结果:
实验2
显示了一在按手机Home键退出时的函数调用时序。 由于不是退出,因此最终没有调用onDestroy(),但是应用变得不可见,因此调用了
onStop。可以看到系统还调用了保存实例状态的函数:onSaveInstanceState(),也就是说按Home键退出到主界面系统会帮助我们
保持Activity的一些信息,同时给了我们保存额外需要维护的信息的机会,这一点请注意,因
为系统不是在任何时候都会调用onSaveInstanceState()的,下面的实验将可以看到。
实验3.Activity1->Activity2
输出结果:
从实验3可以看到系统在Activity1的onPause()之后先将Activity2创建并显示
出来,然后在执行的Activity1后续的操作,onPause()之后Activity1就不再是最前端显示了。
实验4.Activity1->Activity2->Activity1
输出结果:
实验4要注意的是,由于我们使用的是
Intent it = new
Intent(...)
startActivity(it);
的方式,实际上Activity2->Activity1
执行的是创建了一个新的Activity1实例,这和一开始的Activity1不是同一个,也就是说,这里Activity栈里已经有了3个
Activity实例,这一点很容易被弄错,可能界面上是好像回到了Activity1,但实际上完全不同。
实验5.Activity1->Activity2->Activity1->Back键
输出结果:
实验5承接了实验4,只是多按了Back键,这时候系统销毁了一个Activity1实例,栈里还有两个,栈顶的是Activity2,也就是说界面上看见的是Activity2.
实验6.Activity1->Activity2->Home键->Activity1
输出结果:
实验6的特别地方在于,在按了Home键回到主界面后,Activity2也被转到后台,程序走到了onStop(),然后我们重新启动
Activity1应用,可以看到执行onRestart()的是Activity2,而不是Activity1!!这是因为此时Activity2处在
栈顶,这一点也是很容易出错的地方。
实验7.Activity1->屏幕旋转90度
输出结果:
实验7单独列出来也是因为代表了一类Activity被打断的情况,就是系统配置发生了变化,官方文档里也对为什么一定要采用这种先销毁再重新创建的方式做了解释,可以参考Configuration
Changes
一段,我就不再多介绍了,这里只是实际跑了个实验验证。
----------------------------------------------------------------------------------------------
实验就做这么多,其实还可以做更多一些情况的测试,但基本的转换情况这里都已提到。虽然运行,暂停,退出的基本概念大家比较清楚,但是从上面的实验也可以
看到,一些细节仍然需要在设计时考虑清楚,因为毕竟我们无法估计用户的操作序列和系统本身的各种情况,如果要想使我们的应用够健壮,必须充分考虑到
Activity不同状态间转换的问题。
此外,还有一些可以深入探讨的问题:
1.
关于finish()的使用,上面的实验没有用到它,但我们看到前面的实验只有在按Back键的时候系统会销毁当前的Activity,如果处理不当会产
生大量Activity新的实例,而显然很多不是我们需要的,必须以合适的方式在恰当的时机消除,这时就需要finish(),函数使用虽然简单,但是要
用在什么时机和地方是需要考虑的。
2.
关于onSaveInstanceState()的使用,我们前面的实验也说明了,不是任何时候系统都会调用onSaveInstanceState()
的,原因官方文档也提了一些,请仔细阅读,官方举的一个例子是当一个Activity不再处于最前端时,如果系统由于内存原因需要关掉这个
Activity,此时系统会调用onSaveInstanceState(),这样我们才有机会做些保存信息以便将来重启的工作。
3.关于onPause()函数,由于Activity从最前端显示到其他状态的转换会很频繁,这个函数也会很频繁的被调到,而它是一个同步函数,这个操作不完成,后面的操作无法进行,因此请不要在其中做太多操作,造成性能问题。
关于Activity的状态转换还有很多可以研究的地方,以后有机会再贴出来。
分享到:
相关推荐
系统在不同状态间切换时,可能会跳过某些回调,开发者需要根据具体场景进行合理处理。 在实际开发中,还可能遇到Activity的前台和后台概念。前台Activity是指当前与用户交互的Activity,而后台Activity则是在前台...
这篇笔记主要探讨了Activity的生命周期,这是每个Android开发者都需要深入理解的关键概念。Activity的生命周期包括了一系列的状态变化,这些状态反映了Activity在应用程序中的存活状态,以及如何响应系统资源的变化...
通过分析 AMS 的源码,我们可以深入理解 Android 应用的启动流程和状态转换。 4. **ContentProvider** ContentProvider 是 Android 中数据共享的机制,通过 Uri 路径访问数据。学习 ContentProvider 的源码有助于...
理解生命周期和如何在不同状态之间转换是Android开发的基础。 3. **Intent**:Intent用于在不同的组件之间传递消息,包括启动Activity或Service,它是Android系统的核心通信机制。 4. **Service**:Service是后台...
- **Activity生命周期**:笔记详细解释了Activity的各个状态(如运行、暂停、停止、销毁)及其转换,这对于优化应用性能和处理用户交互至关重要。 - **Intent机制**:Intent是Android中启动组件和服务的主要手段,...
2. **Android应用的生命周期**:应用程序在不同状态下有不同的行为表现,例如启动、暂停、停止和销毁等状态。 #### 二、Dalvik虚拟机与Java虚拟机的区别 1. **Dalvik虚拟机与Java虚拟机**: - **Dalvik虚拟机**...
Android的生命周期管理也是重点,如何在不同组件状态之间妥善处理转换,以确保应用性能和用户体验。笔记可能会详细解释每个组件的生命周期方法,并给出最佳实践。 在数据存储方面,笔记会涵盖SQLite数据库的使用,...
这份"Android笔记与笔试题"资料涵盖了Android开发的基础到高级概念,对于开发者或者准备面试的求职者来说是一份宝贵的资源。下面,我们将详细探讨其中可能包含的知识点,并提供一些扩展内容。 1. **Android系统架构...
- 这些函数帮助开发者处理Activity在不同状态之间的过渡。 #### 四、额外知识点 - **Gradle**: Android Studio 使用 Gradle 构建系统来管理项目的依赖关系和构建过程。Gradle 使用 Groovy 语言编写脚本。 - **...
总的来说,这些笔记涵盖了Android中的Intent使用、UI元素(如EditText和Menu)的操作、布局管理(尤其是RelativeLayout的属性)以及基本的交互组件(如RadioGroup和CheckBox)的使用。这些都是Android开发中常见的...
1. Android Studio学习笔记的概览 - 笔记是作者在Android Studio 3.2版本上进行安卓开发学习时遇到的问题记录,涵盖三个多月的学习心得。 2. Android颜色设置 - 学习如何在Android应用中设置和使用颜色,颜色的...
《Android Development Art: Android开发艺术探索,脑图笔记》是一份深入探讨Android应用程序开发的宝贵资源,它以开源的形式提供给广大开发者。这份资料的核心在于帮助开发者深化对Android平台的理解,提升开发技能...
Android全程学习笔记旨在提供一个详尽且全面的指南,涵盖了Android开发中的关键技术点和实践案例。以下是关于Android开发的一些核心知识点: 1. **第一个Android应用**:开发Android应用的起点通常是从创建并运行你...
根据提供的文件信息,我们可以整理出一系列与Android开发相关的知识点,主要面向初学者群体。下面将对这些知识点进行详细的解析。 ### 1. 导入EditText控件 ```java import android.widget.EditText; ``` **知识...
1. Activity生命周期:了解Activity的创建、运行、暂停、停止和销毁等状态及其转换,是理解应用行为的关键。 2. Intent:Intent是Android中启动组件和传递数据的主要方式,它可以启动Activity、Service,或发送广播...
Android的生命周期管理是开发者必须掌握的关键概念,教程会详细阐述各个组件的生命周期状态转换,并给出最佳实践,以防止内存泄漏和应用无响应(ANR)问题。 对于数据存储,教程会讲解Shared Preferences、SQLite...
理解Activity的生命周期以及如何在不同状态间转换是Android开发的关键。启动Activity通常通过Intent对象进行,可以传递数据并启动新的界面。 7. **Broadcast、发送短信与监听短信广播** 广播Receiver是Android中...
根据谢彦于2010年的Android笔记,我们可以总结出一系列关于Android开发的重要知识点,涵盖了系统配置、基本概念、程序开发、以及Android架构层分析等多个方面。以下是对这些知识点的详细说明: ### 1. 系统配置 ###...