Android 回眸Activity

作者: 梵依然 | 来源:发表于2016-05-20 07:30 被阅读255次

    <a name="ActivityLifecycle"></a> <h3>Activity生命周期</h3> <p>系统中的Activities会用一个<em>activity堆栈</em>进行管理.
    当一个新的activity启动之后,它会处在栈顶的位置并成为运行中的activity--之前的activity通常在栈中它之后的位置,直到有新activity出现它才会再次成为前台activity。 <p>一个Activity有四种基本状态:</p> <ul> <li> 如果activity在屏幕前端(栈中最顶端),它是<em>active</em>或<em>running</em>状态。. </li> <li>如果activity已经丢失焦点但是仍然是可见的(也就是说,一个新的不是全屏的或者是透明的activity已经处于activity栈的顶端获得焦点),它会变为<em>paused</em>。一个paused的activity是完全活的(它仍然有所有状态和成员信息,仍然附着在window manager上),但是在系统内存极其不足的情况下会被杀掉。 <li>如果activity完全被另一个activity遮蔽,它就处于<em>stopped</em>状态。它仍然保持所有状态和成员信息,但是对用户不再可见所以它的窗口被隐藏并且当内存在别处需要的时候它通常会被系统杀死</li> <li>如果activity是paused 或 stopped状态,系统可以通过让它结束或只是仅仅杀死它的进程来释放activity的内存。当它再次展现给user的时候,它必须完成restarted并恢复到之前的状态</li> </ul> <p>在activity中你可能感兴趣监测的三个重要的循环: <ul> <li>activity的<b>整个生命周期</b>是在第一次调用onCreate直到最终的onDestory之间。一个activity会在onCreate()中做所有“全局”状态的准备工作,并且所有剩余的资源都会在onDestroy中释放。比如,在后台从网络下载数据的线程,这个线程可以在onCreate()中创建,然后在onDestroy()中停止。 <li> activity<b>可见的生命周期</b>是在onStart和相对应的onStop之间。在这个时间段内,用户可以在屏幕上看到这个activity,即使它没有在前台,没有和用户在交互。在这两个方法之间可以维护需要给用户展示activity所需的资源。比如,可以在onStart中注册广播来监测影响了界面的变化,然后当用户看不见你所展示的内容的时候在onstop()中注销广播。onstart()和onStop()可以被多次调用,activity随之可见和隐藏<li>
    activity的<b>前台生命周期</b>是在onReume和相应的onPause之间。在这个时间段内activity在所有其他activity的最前面并且与用户交互。一个activity可以频繁的在resumed和paused的状态之间转换--比如当设备休眠,当activity的result传递,当一个新的intent传递--所以在这两个方法中的代码应该相当的轻量级。 </ul> <p>通常完整的生命周期是这样的:</p>

    方法 描述 是否能被杀死 下一个方法
    onCreate() 当activity第一次被创建的时候调用。这应该是做所有正常静态设置的地方:创建views,绑定list数据等。这个方法还提供一个Bundle,这个值如果不为空的话用来包含activity之前冻结的状态。这个方法之后通常跟着onStart() No onStart()
    onRestart 在activity停止之后在started之前调用。通常之后跟着onStart() No onStart()
    onStart 当activity对用户来说可见的时候调用 ,如果activity变为前台接下来会是onResume(),如果变为隐藏接下来会是onStop() No onResume()或者onStop
    onResume 当activity将要开始和用户交互的时候调用。这时候activity在activity栈顶。接下来通常是onPause() No onPause()
    onPause 当系统开始恢复一个之前的activity的时候调用。这个方法用来提交没有保存的修改来持久化数据,停止动画和其他继续消耗CPU的事情。这个方法的实现必须快,因为下一个activity在这个方法返回之后才会resumed。如果activity重新回到前端调用onResume,如果变为不可见调用onStop() Pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB} onResume或 onstop
    onStop 当activity不再可见的时候调用,因为另一个activity已经resume并且覆盖了这个activity。 这有可能是因为一个新的activity开始或者这个activity销毁了。如果这个activity重新和用户交互,接下来会调用onRestart()方法;如果这个activity被销毁,会调用onDestroy()。 Yes onRestart或 onDestroy
    onDestroy activity被摧毁前可以接受到的最后的方法调用。这有可能是因为这个activity正在销毁(调用了finish方法,或者系统为了节省空间暂时销毁这个实例。可以通过isFinishing()来区分这两种情况 Yes nothing
     <p>注意表格中的“”Killable”一列--对这些被标记为可以被杀死的方法,在它们返回之后,持有activity的进程有可能在任何时候被系统杀死而不执行它的一行代码。所以应该使用onPause来保存持久化的数据(比如用户编辑的内容)。另外,方法onSaveInstanceState会在activity变为后台之前调用,这样可以允许你在activity给定的bundle中来保存任何动态的实例状态,如果这个activity需要被重建,这个bundle会在之后的onCreate中接收。注意在onPause中保存数据要比在onSaveInstanceState中保存要重要,因为后者不是生命周期中的一部分,所以不会在所有场景下都会被调用。</p>     <p class="note"> 注意这些语义在目标平台是Build.VERSION_CODES#HONEYCOMB以上的比之前的版本会有一些轻微改变。从Honeycomb开始,在onStop返回之后application才会进入可被杀的状态。这样当onSaveInstanceState(Bundle)有可能被调用(它可能会在onPause方法之后安全的被调用)而且应用可以安全的等待直到onstop保存了数据。</p>     <p>对那些没有标记为可杀死的方法,activity所在的进程从方法调用的时候直到它返回都不会被系统杀掉。所以比如说,在onPause之后到onResume开始之前之间activity是处于可以被杀的状态</p>     <a name="ConfigurationChanges"></a>   <h3>Configuration Changes</h3>     <p>如果设备的配置(在Resources.Configuration这个类定义的)改变了,那么所有展示给用户的界面都需要更新来匹配刚刚的配置。因为activity是和用户主要的交互机制,所以它包含特殊的支持来处理配置改变</p>     <p>除非你指定了,否则的话一个配置改变(比如屏幕方向,语言,输入设备等)会使当前的activity销毁,重新调用正常的activity生命周期onPause,onStop,onDestory。如果activity已经在前台或对用户来说可见的,一旦onDestroy被调用,那么一个新的实例会被创建,之前实例在onSaveInstanceState中生成的任何变量都会传递到新实例中。</p>     <p>会这么做是因为所有的应用资源,包括布局文件,都得依据配置值来修改。所以唯一安全的方法来处理configuration改变是重新检索所有资源,包括布局,图片和字符串。因为activity必须已经知道怎样保存它们的状态并且从保存的状态中重建它们,所以在一个配置发生改变的时候使activity重启一下比较方便。</p>     <p> 在一些特殊的情况下,基于一个或一些配置改变,你不想重启你的activity。可以通过在manifest文件中配置android:configChanges属性来处理。所有的你声明要处理的配置修改的类型都会在当前activity的onConfigurationChanged方法中接收到,而不是重启。如果有些配置修改你没有处理,那么activity也会重启然后onConfigurationChanged方法不会再被调用</p>     <a name="SavingPersistentState"></a>   <h3>保存持久状态</h3>     <p>通常有两种持久化状态activity需要处理:共享的类文档的数据(典型的是在Sqlite数据库中使用ContentProvider)和内部状态比如用户配置。</p>     <p> 对于contentProvider数据来说,建议activties使用"edit in place"的用户model。也就是说,任何编辑用户产生的影响都要及时的做出反应,而不再需要额外的确认步骤。支持这种model通常遵循这简单的两条:</p>     <ul>       <li> <p>当创建一个新的文档,后台数据库entry或者文件会立刻被创建。比如,如果用户选择写一封新的邮件,当他们开始输入数据的时候一个新的entry就会创建,所以如果他们在这之后去了其他的activity,这个e-mail就会出现在草稿列表。</p>       <li> <p>当activity的onPause方法调用的时候,它应该把用户做的修改提交给后台content provider 或者文件。这样确保这些修改会被其他所有将要运行的activity看到。你可能想要在activity生命周期的任何关键时刻都要提交你的数据:比如在启动一个新的activity之前,在结束你的activity之前,当用户在输入框内切换的时候等等。</p>   </ul>     <p>这种模式设计用来防止用户在activity之间导航的时候丢失数据,而且允许系统在activity paused之后的任何时候安全的杀死activity。注意这也意味着用户按返回键不代表取消--意味着虽然离开了activity但是当前的内容也被保存了。在activity中取消编辑必须通过其他机制来提供,比如明确的“revert”或者“undo”选项。</p>     <p>getPreferences方法管理着activity持久化状态,允许你检索并修改这个activity关联的键值对集合。为了使用跨多应用组件(activities,receivers,services,providers)共享的preferences,可以使用底层的Context.getSharedPreferences()方法来检索指定名字存储的preferceces对象。(注意它不能垮应用包的共享设置数据--如果想那样做你需要content provider)</p>        <a name="Permissions"></a>   <h3>Permissions</h3>     <p>可以通过在manifest的activity的tag的声明来强制启动一个指定的activity。这样之后其他应用需要声明一个相对应的uses-permission元素来启动那个activity。   <p> 当启动一个activity可以在Intent设置Intent#FLAG_GRANT_READ_URI_PERMISSION   Intent.FLAG_GRANT_READ_URI_PERMISSION} 和/或者 {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION   Intent.FLAG_GRANT_WRITE_URI_PERMISSION}。这样会授予activity可以访问intent中指定的URIs。访问权限会保留着直到activity结束(它将会保持直到宿主进程被杀死和其他临时性破坏)。比如Build.VERSION_CODES#GINGERBREAD这个版本,如果activity已经创建而且新的intent传递到了onNewIntent这个方法,任何最近授予的URI权限会添加给这个activity。   <a name="ProcessLifecycle"></a>   <h3>进程生命周期</h3>     
    

    <p>android系统尽可能长时间的保持应用的进程,但是最终在内存运行不足的时候需要移除旧的进程。就像在Activity生命周期中描述的那样,移除哪个进程的决策密切的与用户的交互状态联系在一起。通常来说,基于activities在进程中的运行情况,按照重要性排序,进程有四种状态。系统会在杀死更重要(最前边的那些)的进程之前杀死不那么重要(最后的那些)的进程。
    <ol>
    <li><p><b>前台activity</b>(在屏幕最顶端的,用户当前正在交互的activity)是最重要的。如果在设备上它使用的内存比可用的内存还要多的时候,它的进程只有在最后手段的时候才会被杀死,通常这时候设备已经达到内存分页的状态,所以这么做来保持用户界面响应。
    <li><p><b>可见activity</b>(activity对用户来说是可见的但不是在前台,比如在一个前台对话框后面)是极其重要并且不会被杀死除非为了保持前台activity运行。
    <li><p><b>后台activity</b>(对用户来说不可见且已经paused)不特别重要,所以系统可能会安全的杀死它的进程来回收内存给前台或可见进程使用。如果它的进程需要被杀死,当用户导航回这个activity(再次使它在屏幕上可见),它的onCreate方法会被调用,并且之前在onSaveInstanceState方法中提供的savedInstanceState这个参数会传递过来,以使它重启之后处于和用户最后离开时一样的状态。
    <li><p><b>空进程</b>没有actiivties或者其他应用组件(比如Service或android.content.BroadcastReceiver类)作为寄主。这些在内存不足的时候会被很快的杀死。所以,任何activity之外的后台操作必须在BroadcastReceiver或Service的上下文中执行来保证系统知道它需要保持你的进程。
    </ol> <p>有时候在Activity中会有运行时间很长的操作,这个操作独立于activity的生命周期。比如:一个照相应用允许你上传一张图片到网站。上传操作会花费很长时间,应用应该允许用户离开这个应用之后,上传仍在继续。要想完成这个操作,activity可以开启一个service。这样在上传这段时间内系统会妥善安排处理(认为它会比那些不可见的应用更重要),和原activity是否paused,stopped,或者finished都无关。

    相关文章

      网友评论

        本文标题:Android 回眸Activity

        本文链接:https://www.haomeiwen.com/subject/nnjqrttx.html