Android官方开发教程中文版4
更新时间:2024-01-13 14:07:01 阅读量: 教育文库 文档下载
Android官方开发教程中文版
管理Activity的生存周期
管理Activity的生存周期
当用户通过导航离开然后又返回你的App,App的Activity实例在它们的生存周期内在两个不同的状态之间转换。例如,Activity首次启动时成为系统的前台并接受用户的关注,在这个过程中,Android系统在你的Activity上调用一系列生命周期方法设置用户界面和其它组件。如果用户执行了一个启动另一个Activity或切换到其它App的动作,系统调用生命周期的其它方法把Activity移到后台(Activity不再可见,但实例和状态仍然完好无损)。
在生命周期的回调方法中,你可以定义当用户离开和重新进入Activity时,Activity的行为。例如,如果你正在创建一个流媒体视频播放器,当用户切换到其它App时,你可以暂停视频并中断网络连接。当用户返回时,你再重新连接网络并允许用户从暂停点恢复播放。
本课程解释了重要的生命周期回调方法,每个Activity实例接收和如何使用它们,使Activity执行用户期望的结果,并且当Activity不需要它们时,不会消耗系统资源。
启动Activity
不像其它编程范例由main()方法启动,Android系统在Activity中通过调用对应生命周期特定阶段的回调方法来启动代码。在启动Activity时有一系列的回调方法,销毁Activity时也有一系列的回调方法。
本节内容提供了大部分重要的生命周期方法的概览,并且展示了在创建Activity的新实例时如何处理首个生命周期的回调。
理解生命周期回调
在Activity的生存期内,系统在一个阶梯状金字塔的序列中调用核心的生命周期方法。也就是说,Activity生命周期的每一个阶段都是这个金字塔上的一个台阶。随着系统创建新的Activity实例,每个回调方法都把Activity的状态向顶部移动一步,当到达顶部时,Activity运行在前台并可以和用户交互。
当用户开始离开Activity时,系统调用其它的回调方法把Activity的状态返回到金字塔底部以消除Activity。在某些情况下,Activity仅仅移动到金字塔的中间并等待(例如用户切换到其它App),Activity可以从这里回到顶部(如果用户返回了Activity)并且从用户离开的地方恢复。
根据Activity的复杂度,你可能不需要实现所有的生命周期方法。不管怎样,重要的是你要理解每个回调方法并能实现它们,以确保你的App表现得如用户期望的那样。正确地实现Activity的生命周期方法以确保你的App在以下几个方面表现良好,包括:
? 用户在使用你的App时接到电话或切换到其它App时,不能崩溃。 ? 用户不再和App频繁交互时,不能浪费宝贵的系统资源。 ? 当用户离开App并在稍后返回时,不能丢失用户的进程。
? 当屏幕在水平和垂直方向间切换时,用户的进程不能丢失或崩溃。
在接下的课程中你将学习到,Activity在图一所示的不同状态间转换的几种情况。任何情况下,这些状态中只有三个会静止不变,也就是说,同一时间只能存在以下三个状态中的一个:
Resumed
这个状态下,Activity运行在前台,并且用户可以和它交互(有时也被称为“Running”状态)。 Paused
这个状态下,Activity被另一个Activity部分遮盖——另一个Activity运行在前台,并且背景是半透明的或者没有覆盖整个屏幕。暂停的Activity不会接收用户输入,也不会执行任何代码。 Stopped
这个状态下,Activity完全隐藏并对用户不可见,它被认为处于后台。当停止时,Activity实例以及它所有的状态信息,如成员变量仍然保持,但不会执行任何代码。 其它状态(Create和Started)非常短暂,系统通过调用下一个生命周期方法,很快从它们移动到下一个状态。也就是说,系统调用onCreate()之后,很快调用onStart(),接着又立即调用onResume()。
这就是Activity生命周期的基本知识,现在你要开始学习某些特定的生命周期行为。
图一:用阶梯状金字塔图解Activity生命周期。展示了每个回调方法是如何使Activity向顶部的Resume状态靠近,还有把Activity带回到底部的回调方法。Activity也可以从Paused和Stopped状态回到Resumed状态。
指定你的App的启动Activity
当用户从Home屏幕上选择你的App图标时,系统在App内为你声明的“执行”(或“主”)Activity调用onCreate()方法。这是你的App用户界面的主入口点。
你可以在Android清单文件中声明哪个Activity成为你的主Activity,AndroidManifest.xml文件在你的项目根目录中。
App的主Activity必须在清单文件的
注意:当你使用Android SDK工具创建Android项目时,默认的项目文件就包括一个用这个过滤器(filter)声明在清单文件中的Activity类。
如果你所有的Activity都没有包含值为MAIN的action和值为LAUNCHAR的category属性,那么你的App图标不会出现在Home屏幕的App列表中。
创建新实例
大多数App都包含了几个Activity以允许执行不同的操作。无论是由用户点击App图标时创建的主Activity,还是你的App在响应用户操作时启动的Activity,系统都会调用onCreate()方法创建Activity的实例。
你必须实现onCreate()方法来执行基本的应用程序启动逻辑,这些逻辑在Activity的整个生存期内只会发生一次。比如,你的onCreate()方法应该定义用户界面和实例化某些类变量。
下例演示了为Activity执行某些基本设置的部分代码,如定义用户界面(在XML布局文件中声明),声明成员变量以及配置某些UI。
TextView mTextView; // 布局中文本视图的成员变量
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
//为当前Activity设置用户界面
// 布局文件定义在项目的res/layout/main_activity.xml 文件中 setContentView(R.layout.main_activity);
// 初始化TextView成员,这样我们可以在后面操作它 mTextView = (TextView) findViewById(R.id.text_message);
// 确保我们运行在Honeycomb或更高版本下,以便使用操作栏API if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // 对主Activity,确保App的图标在操作栏中 // 不要看起来象个按纽
ActionBar actionBar = getActionBar(); actionBar.setHomeButtonEnabled(false); }
}
警告:用SDK_INT这种方式来防止旧系统执行新的API仅在Android2.0(API级别5)或更高版本下有效,旧版本这样做将会产生一个运行时异常。
一旦onCreate()执行完毕,系统会紧接着调用onStart()和onResume()方法,你的Activity永远都不会停留在Created或Started状态。从技术上说,当调用onStart()时,Activity就对用户可见,但onResume()会紧跟着被调用,Activity将保持在Resume状态直到某些事情改变它。比如收到一个电话,用户导航到其它Activity,或者设备屏幕关闭。
在接下来的课程中,你将看到其它启动方法:onStart()和onResume()在Activity从Paused和Stopped状态中恢复时是如何使用的。
注意:onCreate()方法有一个参数savedInstanceState,我们将在稍后的课程“重建Activity”中讨论它。
图二,另一张Activity生命周期结构的图解,当创建Activity新实例时,系统按顺序调用三个主要回调方法:onCreate(),onStart()以及onResume()。一旦这个回调系列的调用完成,Activity将到达Resume状态,用户可以和它交互,直到用户切换到不同的Activity。 销毁Activity
Activity的第一个生命周期回调方法是onCreate(),最后一个生命周期回调方法是onDestroy()。系统调用onDestroy()方法标识着你的Activity从系统内存中完全移除。
大部分App不需要实现这个方法,因为本地类的引用会随Activity一起被销毁,你的Activity应该在onPause()和onStop()中执行大部分的清理。无论如何,如果你的Activity包含了在onCreate()中创建的后台线程或其它长期资源,没有正确关闭的话可能会造成内存泄漏,你应该在onDestroy()中终止它们。
@Override
public void onDestroy() {
super.onDestroy(); // 首先调用基类方法
//停止在onCreate()中开始的对方法的跟踪 android.os.Debug.stopMethodTracing(); }
注意:系统会在任何情况下调用onPause()和onStop()方法后调用onDestroy(),只有一种情况除外:在onCreate()方法内调用了finish()方法。在某些情况下,例如你的Activity临时决定启动另一个Activity,你可以从onCreate()方法内调用finish()以销毁Activity。在这个案例中,系统会在不调用其它任何生命周期方法的情况下立即调用onDestroy()方法。
暂停及恢复Activity
在App正常使用的情况下,有时候前台Activity会被其它可视组件遮挡从而导致Activity暂停。比如一个半透明的Activity(如对话框风格之类的)打开时,之前的Activity会暂停。虽然这个Activity有部分可见,但它当前没有拥有焦点,所以保持在暂停状态。
不管怎样,一旦Activity被全部遮挡而不可见时,它将停止(我们在下一节中讨论)。 Activity进入暂停状态时,系统会调用onPause()方法,以允许你停止正在进行的行为,暂停点(如视频)或任何存留的信息都应该被持久保存以防止用户继续离开你的App。如果用户从暂停状态返回到Activity,系统恢复它并调用onResume()方法。
注意:当Activity收到onPause()的调用,它可能标识着你的Activity将会暂停,然后用户可能会把焦点返回到你的Activity。不管怎样,这通常都是用户离开App的第一个迹象。
当一个半透明Activity遮挡你的Activity时,系统调用onPause()方法并且Activity在暂停状态等待(1),如果用户在仍然暂停时返回Activity,系统将调用onResume()(2)。
暂停Activity
当系统为你的Activity调用onPause()时,技术上意味着你的Activity仍然有部分可见。但更多情况下表示用户正在离开这个Activity,并且Activity将很快进入停止状态。你应该在onPause()回调方法中做到:
? 停止动画或其它消耗CPU的行为。 ? 提交未保存的改变,但只有当用户希望这个改变被持久保存时才这么做(比如一个
Email的草稿)。
? 当Activity暂停并且用户不再需要它们时,释放系统资源。比如广播接收器、对传
感器的操作(GPS之类)或者任何影响电池寿命的资源。
例如,你的应用程序使用了照相机,onPause()方法是释放它的好地方: @Override
public void onPause() {
super.onPause(); //首先调用基类方法
// 释放照相机,因为暂停时我们不需要它 // 而其它Activity可能会使用它 if (mCamera != null) { mCamera.release() mCamera = null; } }
通常情况下,你不应该在onPause()方法中把用户的改变持久保存(比如登录到表单中的个人信息)。只有你确信用户希望这些改变会自动保存时(比如Email草稿),才在onPause()方法中把用户的改变持久储存。任何情况下,你都应该避免在onPause()中执行增加CPU负担的工作,比如写入数据库,因为这可能会使过渡到下一个Activity变得迟缓(你应该在onStop()的关闭操作中执行繁重的工作)。
如果你的Activity被停止了,你应该在onPause()方法中保持操作完成的数量,以允许快速过渡到用户的下一个目标。
注意:当Activity暂停时,Activity实例仍然驻留在内存中并在恢复时重新使用,你不需要重新初始化在Resume状态之前被回调方法创建的组件。
恢复Activity
当Activity从暂停状态中恢复时,系统会调用onResume()方法。
请注意,每当你的Activity进入前台,系统就会调用这个方法,包括它首次被创建时。这样一来,你应该实现onResume()方法来初始化在onPause()方法中释放的组件,以及执行其它在Activity每次进入Resume状态时必须发生的初始化工作(比如开始动画以及初始化仅在用户拥有焦点时用到的组件)。
下面onResume()的示例对应上面的onPause()示例,它初始化了在Activity暂停时释放的照相机。
@Override
public void onResume() {
super.onResume(); //首先调用基类方法
// 当Activity获得用户焦点时得到照相机的实例 if (mCamera == null) {
initializeCamera(); // 对照相机初始化的本地方法 } }
停止和重新启动Activity
在Activity生存周期内正确地停止和重启Activity是一个重要的步骤,它可以确保用户意识到App一直存活并且他们的进度没有丢失。以下几个关键场景中,Activity会停止和重启:
? 用户打开一个新的App窗口,以及从你的App切换到另一个App,你的App中当
前处于前台的Activity被停止。如果用户在“Home”屏幕中执行App图标或从新
App窗口中返回到你的App,Activity重新启动。
? 用户在你的App中执行某个操作启动一个新Activity,当第二个Activity被创建时,
当前Activity停止。如果用户按下“Back”按纽,第一个Activity重新启动。 ? 用户在手机上使用App时,接到电话。 Activity类提供了两个生命周期方法:onStop和onRestart(),它们允许你专门处理Activity的停止和重新启动。不像暂停状态只有部分UI被遮挡,停止状态确保UI不可见,并且用户的焦点处于不同的Activity(或完全不同的App)。
注意:因为Acctivity停止时,系统仍然会把它保留在内存中,你也许不需要在任何情况下都实现onStop(),onRestart()(或onStart())方法。对大部分Activity来说,简单地停止并重启就行了,你只需要在onPause()中暂停正在进行的操作以及断开和系统资源的连接。
当用户离开Activity时,系统调用onStop()停止Activity(1),如果用户从停止中返回,系统调用onRestart()(2),紧接着调用onStart()(3)和onResume()(4)。注意,不管什么情况导致Activity停止,系统都会在调用onStop()之前调用onPause()。
停止Activity
当Activity收到onStop()方法的调用时,它变得不可见并且释放几乎所有不再使用的资
源。Activity一旦停止,如果需要释放内存,系统可能会销毁它的实例。在极端情况下,系统可能简单地杀掉App的进程而不调用onDestroy()。因此,在可能存在内存泄漏的情况下,使用onStop()释放资源非常重要。
虽然onPause()在onStop()之前调用,你应该在onStop()中执行那行更大、更占CPU资源的关闭操作,例如把信息写入数据库。
下面是一个在onStop()中把便笺的草稿内容持久化保存的例子: @Override
protected void onStop() {
super.onStop(); //首先调用基类方法
// 保存便笺当前的草稿,因为Activity正在停止 // 我们不希望当前便笺的进度被丢失
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
getContentResolver().update(
mUri, // 要更新的便笺的URI
values, // 列名映射以及应用到上面的新值 null, // 未使用SELECT参数 null // 未使用WHERE参数 ); }
当Activity停止时,Activity实例仍然驻留在内存中并在恢复时重新使用,你不需要重新初始化在Resume状态之前被回调方法创建的组件。系统会对布局中的每个视图保持跟踪,如果用户在一个EditText部件中输入了文本,文本将会被保留,所以你不需要保存和恢复它。
注意:即使系统在Activity停止时把它销毁,视图对象(如EditText中的文本)的状态仍然保留在Bundle(键值对中的一个)中,并且在用户返回到Activity同一个实例时恢复它们(下一节讨论更多关于使用Bundle保存其它状态数据以防止Activity被销毁和重建的内容)。
启动/重新启动Activity
Activity从停止状态返回到前台时会调用onRestart()。每当Activity成为可见时,系统都会调用onStart()方法(whether being restarted or created for the first time),只有Activity从停止状态中恢复时才会调用onRestart()方法,如果Activity只是被停止而没有被销毁,你可能有必要在onRestart()方法中执行一些特殊的恢复工作。
App使用onRestart()恢复Activity状态的情况很少见,因此对这种应用方式没有任何指南。因为在onStop()方法中清除了Activity的所有资源,所以你需要在Activity重新启动时重新初始化它们。另外,Activity首次创建时,你也需要实例化这些资源(当它们在Activity实例中还不存在时)。基于此,你应该用onStart()方法来对应onStop()方法,因为系统在创建Activity和从停止状态中恢复Activity时都会调用onStart()方法。
例如,在返回App之前,用户可能已经离开很长时间了,onStart()方法是一个用来验证所需的系统功能是否还允许的好地方。
@Override
protected void onStart() {
super.onStart(); //首先调用基类方法
// Activity可能是首次启动或重新启动 // 我们应该确保GPS功能已经启用 LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE); boolean gpsEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsEnabled) {
// 创建一个对话框要求用户启用GPS,当用户点击“OK”时,
// 用 android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS操作 // 打开设置屏幕,以便用户启用GPS。 }
}
@Override
protected void onRestart() {
super.onRestart(); //首先调用基类方法
// Activity从停止状态中恢复 }
重建Ativity
某些情况下,Activity被销毁是App的正常行为。比如用户按下“Back”按纽,或是Activity明确调用finish()方法来摧毁自己。如果Activity处于停止中,并且用户很长时间都没有使用它,或是前台Activity需要更多系统资源,系统不得不关闭后台进程以恢复内存,系统也可能会销毁Activity。
当Activity因为用户按下“Back”按纽或通过finish()方法结束自己时,由于这些行为表示Activity不再需要,系统会认为Activity实例永久消失。如果Activity被系统强制(相对于App的正常行为)销毁,虽然Activity实例已经消亡,但系统会“记得”它曾经存在,如果用户导航回来,系统会使用销毁时保存的数据和状态描述来创建新的Activity。系统用来恢复之前的状态(被称为“实例状态”)的这些数据保存在Bundle对象的键值对集合中。
警告:用户每次旋转屏幕时,Activity都会被销毁并重新创建。当屏幕方向改变时,系统销毁并重建前台Activity,因为屏幕设置发生变化,而且Activity可能要加载可替换资源(如布局)。
默认情况下,系统使用Bundle实例状态保存Activity中每个视图对象的信息(如EditText对象中的文本值)。所以当Activity被销毁和重建时,不需要通过代码来恢复布局状态。Activity可以有更多你想恢复的状态信息,比如一个跟踪用户进度的成员变量。
注意:要让Android系统恢复Activity中的视图状态,每个视图必须有一个唯一ID,由android:id属性提供。
要保存有关Activity状态的额外数据,你必须重写onSaveInstaneState()回调方法。当用户离开Activity时,系统调用这个方法并传递Bundle对象,在Activity被意外摧毁时保存Bundle对象。如果系统必须在稍后重建Activity实例,它会把相同的Bundle对象传递给onRestoreInstance()和onCreate()方法。
系统开始停止Activity时,它调用onSaveInstance()(1),你可以在这里指定Activity重建时需要恢
复的额外的状态数据。如果Activity被摧毁并要重建相同实例,系统会把(1)中定义的状态数据
传递给onCreate()(2)和onRestoreInstance()(3)方法。
保存Activity状态
当Activity开始停止时,系统调用onSaveInstance()方法,Activity可以使用键值对集合保存状态信息。这个方法的默认实现会保存Activity视图层次的状态信息,比如EditText的文本或ListView的滚动条位置。
要保存Activity的额外状态信息,你必须实现onSaveInstance()方法并向Bundle对象中添中键值对,例如:
static final String STATE_SCORE = \static final String STATE_LEVEL = \...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// 保存用户当前的游戏状态
savedInstanceState.putInt(STATE_SCORE, mCurrentScore); savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// 总是调用基类方法,这样它可以保存视图层次状态 super.onSaveInstanceState(savedInstanceState); }
警告:永远要调用onSaveInstance()的基类实现,默认的实现会保存视图层次的状态。
恢复Activity状态
当Activity在销毁后重建时,你可以从系统传递给Activity的Bundle中恢复保存的状态。onCreate()和onRestoreInstance()方法都会收到相同的Bundle对象,它包含实例状态信息。
因为系统创建Activity的新实例或是重建之前的Activity都会调用onCreate()方法,所以你在尝试读取Bundle对象之前必须检查它是否为null。如果为null,系统在创建新的实例,否则就是恢复之前被摧毁的Activity。
下例是如何在onCreate()中恢复某些状态数据: @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 首先调用基类
// 检查是否在重建之前摧毁的实例 if (savedInstanceState != null) {
// 从保存的状态中恢复成员的值
mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); } else {
// 可能需要为新实例初始化成员的默认值 } ... }
你也可以选择实现onRestoreInstance()来替换onCreate()以恢复状态,系统会在onStart()
方法后调用它。系统仅在恢复保存的状态时才会调用onRestoreInstance()方法,所以你不需要检查Bundle对象是否为空。
public void onRestoreInstanceState(Bundle savedInstanceState) { // 总是调用基类方法,它能恢复视图层次
super.onRestoreInstanceState(savedInstanceState);
// 从保存的实例中恢复状态成员
mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); }
警告:永远要调用onRestoreInstance()的基类实现,默认的实现会恢复视图层次的状态。
学习更多有关在运行时重新启动事件中重建Activity的内容(如屏幕旋转),请参考“处理运行时的改变”。
方法后调用它。系统仅在恢复保存的状态时才会调用onRestoreInstance()方法,所以你不需要检查Bundle对象是否为空。
public void onRestoreInstanceState(Bundle savedInstanceState) { // 总是调用基类方法,它能恢复视图层次
super.onRestoreInstanceState(savedInstanceState);
// 从保存的实例中恢复状态成员
mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); }
警告:永远要调用onRestoreInstance()的基类实现,默认的实现会恢复视图层次的状态。
学习更多有关在运行时重新启动事件中重建Activity的内容(如屏幕旋转),请参考“处理运行时的改变”。
正在阅读:
Android官方开发教程中文版401-13
太原公交IC卡自行车卡充值点05-18
员工行为规范07-10
八年级(上)科学期中期末复习测试卷(四)(第一章综合B卷)01-23
狮子和老鼠作文500字06-26
2019届二轮复习语法专题16种时态经典总结(12页word版)10-21
煮米饭作文600字06-27
钉钉管理员认证考试 部分试题(含答案)04-14
微观经济学习题答案 胡金荣01-05
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 中文版
- Android
- 教程
- 官方
- 开发
- 2017-2018学年江苏省苏州市高一下学期学业质量阳光指标调研英语试题 - 图文
- 五四青年节作文2015年初一关于青年节的作文4篇
- 合同法综合练习+期未指导+历年试卷单项选择
- 管理运筹学第三版习题答案(全)
- 浙大JAVA 实验题答案10answer
- 江苏省无锡市2017-2018学年高一下学期期末考试 语文 Word版含答案
- 冲刺实验班甘肃西北师大附中2019中考提前自主招生数学模拟试卷(6)附解析
- 工程变更管理办法
- Slofed湖州师范学院医学院2009年度学生科研情况总结 - 图文
- 江苏省苏州市2017-2018学年高一下第二学期期末调研英语试题含答案 - 图文
- 沙湾地税文化建设的实践与思考
- 吉源物业公司程序文件(DOC 18页)
- 工程质量保修协议书(户外工程分包)(2)
- 运营管理习题
- 试论加强基层海关队伍建设新举措
- 《篮球行进间运球》教学设计
- 切实加强对社区矫正人员和刑释解教人员的管理和监控力度
- 常见病句类型
- 书评写作规范
- 思想政治教育教学方法论8-4