Activity进阶笔记

正常生命周期的方法

  1. onCreate:此方法在Activity创建的时候回调
  2. onRestart:此方法在Activity不可见之后,重新变为可见的过程中时候会回调
  3. onStart:此方法在Activity可见的时候回调,但是此时Activity处在后台,也就是说用户无法进行操作
  4. onResume:同样是可见的时候回调,而此时已经是在前台了,用户可以正常操作界面了
  5. onPause:从前台变为后台的时候,会被调用,比如用户启动了一个透明的Activity,那么之前的Activity就会调用onPause,进入后台。
  6. onStop:Activity不可见的时候会被调用,比如按下Home键,回到桌面,则会调用onPause和onStop
  7. onDestory:Activity被正常销毁的时候会被调用

在启动另外一个Activity的时候,会先调用onPause方法,然后调用第二个Activity的onCreate , onStart, onResume,然后再调用第一个的onStop方法。

所以,不能在onPause方法中进行耗时的操作,否则会影响第二个Activity的启动。同样,onStop也不应该太耗时,onDestory方法可以用来最终的释放资源。

Activity异常情况下的生命周期

  1. 当资源相关的系统配置发生改变Activity被杀死并重新创建

    比如当屏幕尺寸发送改变的时候(旋转屏幕),Activity其实是被销毁了,并重新创建了一个Activity。

    所以先会执行普通的销毁过程onPause->onStop->onDestory,但是在其中会有一步onSaveInstanceState,在onPause之后,用来保存view的状态。

    然后重新启动的时候,会在onRestoreInstanceState里面恢复view之前的状态,此方法调用在onStart之后。

    思考:不是异常情况下,onSaveInstanceState方法也会被调用,但是不会调用onRestoreInstanceState方法。

  2. 如何防止重新创建Activity?

    android:configChanges="orientation|screenSize"在AndroidManifest中,为Activity配置此属性即可防止在翻转屏幕的重新创建Activity。

    取而代之的是会回调onConfigurationChanged方法

  3. 内存不足的时候,系统很可能会杀死在后台的Activity,生命过程与上面一样。

    思考:系统杀死的时候似乎直接结束的进程,而不会走一遍销毁的生命周期。

Activity启动模式

四种启动模式:

设置启动模式:在AndroidManifest中为Activity设置launchMode=""即可。

  1. standard

    这是默认的启动模式,被启动的Activity B如果是standard模式,那么B的新的实例会被创建并加入到启动它的任务栈的栈顶。(Service是没有任务栈的,所以通过Service启动的时候,会报错,要添加FLAG_ACTIVITY_NEW_TASK flag才能启动,这相当于是singleTask模式启动)

  2. singleTop

    与上面的类似,只不过如果B在栈顶,那么不会再创建新的实例。方法的调用:onPause->onNewIntent->onResume。如果B不在栈顶,则会创建新的实例。

  3. singleTask

    这是栈内复用模式。启动Activity的时候,会先查询是否已经存在了任务栈,如果不存在,那么会先创建任务栈,然后再创建实例压栈。如果已经存在,那么会直接在目标栈内寻找实例。如果存在实例,那么会将目标调到栈顶(其之上的会弹栈,也就是有clearTop的效果),如果不存在实例,那么会创建新实例并压栈。

  4. singleInstance

    这个是单实例模式。此模式的Activity只能单独位于一个任务栈中。所以,一旦创建,以后就不会创建新的Activity了,除非该Activity被销毁。

通过上面几种模式的总结,可以思考一个问题:APP的MainActivity适合哪种模式?

适合singleTask模式,因为我们在其他界面回到MainActivity,也就是主界面,那么其他的界面都应该被销毁,而不是按back键能够返回去。所以singleTask可以帮助我们clearTop。

如何指定任务栈?

​ 在AndroidManifest中,为Activity设置android:taskAffinity=""即可,里面填写的值不要与app包名一样,否则是同一个任务栈。默认的任务栈名称是包名。

Activity的Flags

​ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

  1. FLAG_ACTIVITY_NEW_TASK
  2. FLAG_ACTIVITY_SINGLE_TOP
  3. FLAG_ACTIVITY_CLEAR_TOP
  4. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

隐式启动

IntentFilter匹配规则

intent-filter主要可以配置三个参数,action,category,data.

一个intent只有同时匹配action,category,data才算匹配成功

一个Activity可以配置多个intent-filter,只要匹配上了一个intent-filter就可以启动该Activity。

  1. action

    intent必须要指定一个action,不然会直接匹配失败。

    只要匹配成功一个action即可。

  2. category

    一定要有一个值为<category android:name="android.intent.category.DEFAULT"></category>的category,不然intent会匹配失败。在startActivity的时候,系统会自动给intent加上android.intent.category.DEFAULT,所以在AndroidManifest文件中,必须要加才行,不然没法匹配。

    如果你的intent设置了多个category,那么设置的必须要全部能够被匹配上才行!!!

  3. data

                    <data android:scheme="http"
                        android:host="www.baidu.com"
                        android:port="80"
                        android:path="/search/info"
                        android:mimeType="text/plain"
                        ></data>
    

    data分为两部分,URI和mineType:URI是路径,而mineType是类型

    可以不指定URI,系统会默认指定为content和file,也就是说,在intent中,必须指定Data为content或file才行。

    intent.setDataAndType(Uri.parse("file://abc"),"image/png");

推荐阅读更多精彩内容