在应用程序中至少包含一个用来处理应用程序的主UI功能的主界面屏幕。这个主界面一般由多个Fragment组成,并由一组次要Activity支持。要在屏幕之间切换,就必须要启动一个新的Activity。一般的Activity都占据了整个显示屏,但可以创建成半透明或二者浮动的Activity。
通过继承Activity类可以创建一个Activity窗口,基本框架如下:
1 public class MyActivity extends Activity { 2 @Override 3 protected void onCreate(Bundle savedInstanceState) { 4 super.onCreate(savedInstanceState); 5 } 6 }
以上代码是一个空的Activity,可以通过使用Fragment、布局和视图来创建UI。视图是用来显示数据和提供交互交互的UI控件。Android提供给了多个布局类,成为ViewGroup,它可以包含多个视图来帮助UI布局。Fragment用来封装UI的各个部分,从而能够方便的创建动态界面,这些界面能够针对不同的屏幕尺寸很方向重新排列,起到优化UI的效果。
要想把一个UI分配给一个Activity,需要在onCreate()方法中调用setContentView()方法。可以通过在java代码中创建布局,也可以通过调用xml布局资源文件来创建。如下两种方式:
1 protected void onCreate(Bundle savedInstanceState) { 2 super.onCreate(savedInstanceState); 3 TextView tvShow = new TextView(this); 4 setContentView(tvShow); 5 tvShow.setText("你好"); 6 }
当然,通过调用xml布局文件来创建UI的方法更常用,如下:
1 protected void onCreate(Bundle savedInstanceState) { 2 super.onCreate(savedInstanceState); 3 setContentView(R.layout.activity_main); 4 }
最后,创建好了Activity类不要忘了在Manifest中对其注册。(注册方法及原因请参考: Android高级编程笔记(二)Manifest文件节点详解 )
需要注意的是,想让一个Activity可以被应用程序启动器使用,它必须包含一个监听MAIN动作和LAUNCHER分类的Intent-Filter,如下:
1 <activity 2 android:name="com.codingblock.myactivity.MyActivity" 3 android:label="@string/app_name" > 4 <intent-filter> 5 <action android:name="android.intent.action.MAIN" /> 6 <category android:name="android.intent.category.LAUNCHER" /> 7 </intent-filter> 8 </activity>
正确理解Activity的生存期,可以更好的对应用程序管理资源,从而让应用程序更加连贯流畅。
每一个Activity的状态是由他在Activity栈中所处的位置所决定的,Activity栈是当前所有正在运行的Activity的后进先出的集合。当一个新Activity启动,它就会变成Activity状态,并移到栈顶,当返回到前一个Activity,前台Activity被关闭,那么站总的下一个Activity就会移动到栈顶,变成活动状态。
随着Activity的创建和销毁,从栈中移进移出的过程中他们经历了如下4种可能的状态:
· 活动状态:当一个Activity处于栈顶是,它是可见的、具有焦点的前台Activity并可以接受用户输入。
· 暂停状态:Activity可见,但没有焦点,不能接受用户输入事件。(例如:当一个透明的或者非全屏的Activity位于该Activity之前时)
· 停止状态:Activity不可见。此时,Activity仍然会保留在内存中,保存所有状态信息,然而当系统的其他地方要求使用使用内存时,会优先终止此类状态的Activity。
· 非活动状态:Activity被终止。此时Activity已经从栈中移除了。
为了保证Activity可以对状态改变做出反应,Android提供了一系列的回调方法,当Activity的状态改变时它们就会被触发。以下代码是整个Activity生存期的框架,各方法的说明已在代码注释中详细给出:
1 public class MyActivity extends Activity { 2 3 //在完整生存期开始调用 4 @Override 5 protected void onCreate(Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 //初始化Activity并填充UI 8 } 9 10 //在onCreate方法完成后调用,用于恢复UI状态 11 @Override 12 protected void onRestoreInstanceState(Bundle savedInstanceState) { 13 super.onRestoreInstanceState(savedInstanceState); 14 /* 15 * 从savedInstanceState恢复UI状态 16 * 这个Bundle也被传递给了onCreate 17 * 自Activity上次可见之后,只有系统终止了该Activity时,才会被调用 18 */ 19 } 20 21 //在随后的Activity进程可见生存期之前调用 22 @Override 23 protected void onRestart() { 24 super.onRestart(); 25 //加载改变,知道Activity在此进程中已经可见 26 } 27 28 //在可见生存期的开始时调用 29 @Override 30 protected void onStart() { 31 super.onStart(); 32 //既然Activity可见,就应用任何要求的UI Change 33 } 34 35 //在Activity状态生存期开始时调用 36 @Override 37 protected void onResume() { 38 super.onResume(); 39 /* 40 * 恢复Activity需要,但是当它处于不活动状态时被挂起的暂停的UI更新、线程或进程 41 * 在Activity状态生命周期结束的时候滴啊用,用来保存UI状态的改变 42 */ 43 } 44 45 //在UI状态改变保存到saveInstanceState 46 @Override 47 protected void onSaveInstanceState(Bundle outState) { 48 super.onSaveInstanceState(outState); 49 /* 50 * 如果进程被运行时终止并被重启, 51 * 那么这个Bundle将被传递给onCreate和onRestoreInstanceState 52 */ 53 } 54 55 //在Activity状态生存期结束时调用 56 @Override 57 protected void onPause() { 58 super.onPause(); 59 /* 60 * 挂起不需要更新的UI更新、线程或者CPU密集的进程 61 * 当Activity不是前台的活动状态的Activity时 62 */ 63 } 64 65 //在可见生存期结束时调用 66 @Override 67 protected void onStop() { 68 super.onStop(); 69 /* 70 * 挂起不需要的UI更新、线程或处理 71 * 当Activity不可见时,保存所有的编辑或者状态改变,因为在调用这个方法后,京城可能会被终止 72 */ 73 } 74 75 //在完整生存期结束时调用 76 @Override 77 protected void onDestroy() { 78 super.onDestroy(); 79 /* 80 * 清理所有的资源,包括结束线程、 81 * 关闭数据库连接等 82 */ 83 } 84 }
在一个Activity从创建到销毁的完整的生存期内,它会经历活动生存期和可见生存期的一次或者多次重复。每一次转化都会触发以上方法处理程序。
· 完整生存期: 对onCreate()的第一次调用和对onDestroy()的最后一次调用之间的时间范围。有时候还会发生一个Activity的进程终止,却没有调用onDestroy方法的情况。
使用onCreate方法初始化Activity,如果Activity意外终止,onCreate方法接受一个包含UI状态的Bundle对象,该对象是在最后一次调用onSaveInstanceState时保存的。应该使用这个Bundle将UI恢复为上一次的状态,既可以通过onCreate方法也可以重写onRestoreInstanceState。
对象的快速创建和销毁会导致额外的垃圾收集过程,为了保证代码高效,尽量不要创建短期对象。如果Activity是有规律的创建相同的对象集,可以考虑在onCreate创建,因为onCreate只在Activity生存期调用一次。
· 可见生存期:onStart和onStop之见的时间。此时,Activity可见,但可能没有焦点,或者可能被部分遮挡了。Activity在完整生存期期间可能会包含多个可见生存期。在个别极端情况下,Android运行时可能会在一个Activity位于可见生存期事把它终止,而不调用onStop方法。
onStop方法应该用来暂停或者停止动画、线程、传感器监听器、GPS查找、定时器、Service或者其他专门用于更新用户界面的进程。当UI再次启动时,可以用onStart或者onRestart方法来恢复或者重启这些进程。
onRestart在除了对onStart方法的第一次调用之外的所有方法之前被立即调用。可以用它完程只有当Activity在它的完整生存期之内重启时才能完成的特殊处理。
onStart/onStop方法也可以用来注册或者注销那些专门用来更新用户界面的Broadcast Reciver。
· 活动生存期:onResume及其对应的onPause之间的时间。
当Activity处于活动期时,它在前台,并可以接收用户输入事件。Activity被销毁前可能会经历多个活动生存期,在失去焦点是,活动生存期就结束了。尽量让onPause和onResume方法中的代码执行迅速,尽可能少。以保证前后台切换时能够保持响应。
onResume方法可以是轻量级的。使用它可以重新注册已经使用onPause停止的Broadcast Receiver或者其他进程。