本文接着上一篇写:
配置改变
如果设备的配置(被定义为Resources.Configuration类)被改变了,那么所有显示用户界面的都需要被更新以适应新的配置。因为Acitivity是和用户交互的首要机制,它包含了对配置文件改变的特殊支持。
除非你特殊指定,否则,配置文件的改变将会导致你当前的activity被销毁,经历了一个正常的activity的生命周期:onPause()、onStop(0和onDestroy()。如果此activity目前处在屏幕的最前端,或者是对用户可见,一旦那个activity实例的onDestroy()被调用,那么一个新的activity实例将会被创建,并且新创建的实例将会从 onSaveInstanceState(Bundle)中获得之前那个activity的状态。为什么要这么做呢?是因为任何应用程序的资源,包括布局文件,都能够因为任何配置文件中的配置值而发生改变。因此,对待配置文件的改变最保险的方式就是重新获得所有的资源,包括布局文件,图片资源以及字符资源。由于activity一定知道如何保存他们自己的状态并且利用这些状态重新创建自己,这就是一个简便的方法,让activity利用新的配置文件重启自己!
在一些特殊的情况下,你可能想基于一种或者多种配置文件的改变而避开重启你的activity,这可以通过manifest文件中的 android:configChanges属性来实现。对你声明在此的任何类型的配置文件的改变,你都将再你的activity中调用onConfigurationChanged(Configuration)方法,而不是通常的重启行为。如果出现了一些你并未在此声明的配置文件改变类型,那么,此activity将会重启并且onConfigurationChanged(Configuration)将不会被调用!
启动Activities并获取结果
startActivity(Intent)方法被用来启动一个新的activity,新启动的activity将会位于栈顶,该方法仅有一个参数,一个 Intent,该Intent被用来描述即将被启动的那个activity。
有的时候你也许希望当一个activity结束的时候可以从期中获得一个结果。例如:你可能会启动一个activity使得用户可以从联系人列表中选取一个记录,当选取结束后,该activity可以返回你选中的记录。为了达到这样的目的,你可以调用startActivityForResult(Intent, int)这个方法来启动activity,该方法包含第二个参数,用于标识本次调用的一个整数,该方法的返回值会通过 onActivityResult(int, int, Intent)方法返回。
当一个activity已经存在,那么他就可以调用setResult(int)返回数据给它的持有者,他必须总是提供一个返回码,可以使标准的结果RESULT_CANCELED, RESULT_OK或者是任何从RESULT_FIRST_USER开始自定义的代码。另外,它可以返回一个可选的intent,这个intent可以包含任何你想要的数据。所有的这些信息都会返回给它的持有者的Activity.onActivityResult(),伴随着前面提到的整型参数。
如果一个子activity由于任何原因失败了(例如:崩溃),那么父activity将会收到RESULT_CANCELED的返回码。
保存连续的状态
activity一般需要处理两种持续的状态:一种是共享的文档类型的数据(典型的是利用content_provider存储再SQLite中);另一种是内部状态例如:用户的偏好。
对于content provider数据,建议activities利用本地编辑的模型。那就是,用户做出的任何编辑都会立即产生作用,而不需要额外的确认的步骤,支持这种模型需要遵守如下两条规则:
1、当创建一个新的文档,那么备份的数据库条目和文件就会立即被创建。例如:当用户要写一个新的邮件时,那么一条新的记录就会随着开始输入数据而被创建,以至于如果用户浏览其他的activity,这个邮件将会出现在草稿箱中。
2、当activity的onPause()方法被调用,那么他就会把用户做出的任何改变提交到后端的content provider或者是文件。这将会确保那些改变对于那些即将运行的activity是可见的,你可能会想在activity的生命周期中更加积极主动的保存数据,例如:在启动一个新的activity之前,在结束一个activity之前,当用户改变输入框时。
这个模型被设计用来在用户浏览多个activity防址数据的丢失,并且允许系统在activity被暂停之后安全的杀死它。这意味着用户按下BACK键并不意味着“取消”,而是意味着保存当前的activity的内容并且离开当前的activity,在一个activity中取消编辑需要通过其他的一些机制,例如一个明确的“恢复”或者“撤销”选项。
关于content providers的详细内容可以查阅 content package,这些都是关于在activities之间调用和传播数据的不同之处重要方面。
Activity同样提供了API来管理与activity有关联的持续的状态。这都是可以被拿来使用的,例如:要记住用户的日历显示(日视图还是周视图)或者浏览器的默认主页。
Activity持久的状态是通过getPreference(int)来管理的,允许你去获取并修改一系列和activity有关的键值对。对于多个应用程序组件(activities,receivers,services,provides)共享的偏好设置,你可以通过隐含的Context.getSharedPreferences()方法来通过特殊的名字获取偏好设置的一些对象。(注意:再多个应用程序包中共享设置的数据是不可能的,对于这种情况,你需要使用content provider).
下面有一个从存有用户设定的显示模式的calendar activity中摘抄的一些内容:
public class CalendarActivity extends Activity { ... static final int DAY_VIEW_MODE = 0; static final int WEEK_VIEW_MODE = 1; private SharedPreferences mPrefs; private int mCurViewMode; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SharedPreferences mPrefs = getSharedPreferences(); mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE); } protected void onPause() { super.onPause(); SharedPreferences.Editor ed = mPrefs.edit(); ed.putInt("view_mode", mCurViewMode); ed.commit(); } }
权限
启动特殊activity的权利是在manifest文件中的<activity>标签中声明后被强制执行的。通过这种做法,其他的应用程序需要再他们自己的manifest文件中声明相应的<uses-permission>元素才能启动上面所说的特殊的activity。
要想查看详细的关于权限和安全的内容,可以查阅Security and Permissions文档。
Android系统试图尽可能的保持进程,但是不幸的是,当系统内存过低时,系统不得不杀死一些老的进程来释放内存空间。进程也有四种状态,这四种状态都是基于运行再进程中的activity的状态,系统会优先杀死一些不太重要的进程而不是杀死重要的进程。
1、前台的activity
2、可见的activity
3、后台的activity
4、空的进程
有的时候,一个Activity也许需要长时间的运行,即要独立的存在于它自己的activity生命周期,一个例子就是:也许照相的应用程序允许你上传照片到网上,而上传可能会需要比较长的时间,那么这个应用程序应当允许用户离开上传照片的activity,但是上传照片的进程还是要处于运行状态。为了达到这样的目的,你的应用程序需要再你上传照片的地方开启一个service。这就允许系统给你的应用赋于恰当的优先级,独立于你原来的activity,不管原来的activity处于paused、stopped或者是finished。