10.AMS内部原理

AMS所提供的主要功能包括以下几项:

  • 统一调度各应用程序的Activity.应用程序要运行Activity,会首先报告给AMS,然后由AMS决定该Activity是否可以启动,如果可以,AMS再通知应用程序运行指定的Activity.换句话说,运行Activity时各应用程序的内政,AMS并不干预,但是AMS必须知道各应用程序都运行了哪些Activity.
  • 内存管理,Activity退出后,其所在的进程并不会被立即杀死,从而下次在启动该Activity时能够提高启动速度.这些Activity只有当系统内存紧张时,才会被自动杀死,应用程序不用关心这个问题,这些正是AMS中完成的.
  • 进程管理,AMS向外提供了查询系统正在运行的进程信息的API

AMS中定义了几个重要的数据类,分别用来保存进程(Process),活动(Activity)和任务(Task).

进程数据类ProcessRecord.

变量作用 主要包含
进程文件信息 与进程对应的APK文件的内部信息,比如 String processNme,ArrayMap pkgList;// 运行在当前进程的所有packages
进程的内存状态信息 这些信息将用于Linux系统的OOM情况的处理,当发生系统内存不够用时,Linux会根据进程的内存状态信息,杀掉优先级比较低的进程; int maxAdj; int curAdj;
进程中包含的Activity,Provider,Service等 ArrayList activities;ArrayList recentTasks;ArraySet services;ArraySet executingServices;ArraySet connections;ArraySet receivers

ActivityRecord数据类

变量作用 主要包含
环境信息 Activity的工作环境,比如,隶属于哪个package,所在的进程名称,文件路径,数据路径,图标,主题等 String packageName;String processName;String taskAffinity;int labelRes;int theme;int windowFlags;
运行状态信息 比如idle,stop,finishing等boolean sleeping;boolean nowVisible;boolean idle;boolean hasBeenLaunched;boolean immersive;

AMS中使用任务的概念确保Activity启动和退出的顺序.Android的设计理念遵守了一个简单的原则.即如果是跨Task切换,调用者是没有权利更改被调Task里面的Activity顺序的,除非被调者自己声明了某些属性.这个原则是合理的,因为只有用户有权利去更改自己当前所操作的Task中的Activity顺序.

系统提供了两种方式完成Task的切换,第一种是在AndroidManifest.xml文件中声明Activity自身的启动属性,另一种是在启动时给intent中添加不同的flag.前者包括:

  • android:launchMode = standard/singleTop/singleTask/singleInstance
  • android:clearTaskOnLaunch = true/false
  • android:finishOnTaskLaunch = true/false
  • android:allowTaskReparent = true/false

后者包括:

  • Intent.FLAG_ACTIVITY_NEW_TASK
  • Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
  • Intent.FLAG_ACTIVITY_CLEAR_TOP
  • Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
  • Intent.FLAG_ACTIVITY_NO_HISTORY
  • Intent.FLAG_ACTIVITY_SINGLE_TOP

这些设置按照功能可分为三类,第一类是为了完成在Task之间切换,第二类是为了完成在当前Task中改变Activity的顺序,第三类是为了在Task切换时Task内部自动重排所属的Activity.

  • 第一类,在Task之间切换,具体实现就是在启动的intent中设置FLAG_ACTIVITY_NEW_TASK.如果intent所匹配到的Activity已经存在于已有的Task中,那么就切换Task,如果没有,则创建一个新的Task.而这只是一种实现方式,实际的需求有时是调用者希望被调用者出现在一个新的Task中,有时则是被调者要求自己必须在一个新的Task中,对于后者,则使用launchMode来完成.
  • 第二类,在同一个Task中调整Activity的顺序,由于这些FLAG是用于在当前Task中切换的,因此不能和NEW_TASK标识一起使用.这类常见的包括以下几种.

    • CLEAR_TOP,作用是清除目标Activity上面的Activity
    • REORDER_TO_FRONT,简单重排
    • NO_HISTORY,目标Activity不会出现在mHistory中
  • 第三类,允许被调Task在启动前主动重排.首先调用者要发起这个请求,其次是被调者要有这个功能.发起是通过设置intent标识为RESET_IF_NEEDED实现的,而功能是在manifest文件中使用android:clearTaskOnLaunch和android:finishOnTaskLaunch属性.

发起Activity A启动Activity B,Activity A的pause和stop主要区别有以下几点:

  • 发生在不同的时机,pause发生在目标Activity启动之前,stop发生在目标Activity启动之后
  • 回调Activity的不同函数
  • 被调方式不同,pause是AMS有意调用的,而stop则是AMS无意为之.

在完成启动目标Activity后,会往Handler中添加IdleHandler,在IdleHandler中会执行AMS的activityIdle方法,该函数内部会辗转调用到stopActivityLocked()方法.

尽管可以在Activity的onKeyDown()函数中截获Back键,但是却不能够截获Home键,其原因是WMS在进行消息派发时,对Home键做了默认处理,而没有把它派发到应用程序里面去.Back键不是系统按键,但是Back键却有默认的处理方法,应用程序可以在Activity的onKeyDown()方法中截获该消息.长按Home键也是系统消息,应用程序无法对长按Home键的消息做自定义处理.

Activity中所有和状态相关的回调函数.

回调函数名称 使用场合
onCreate() Activity实例被创建后第一次运行时
onNewIntent() 有两种情况会执行回调:Intent的flag中包含CLEAR_TOP,并且目标Activity已经存在当前任务队列中,Intent的flag中包括SINGLE_TOP,并且目标Activity已经存在当前任务队列中.
onStart() Activity从stop状态重新运行时
onRestoreInstanceState(Bundle savedInstance) 与onPostCreate()相同,只是先于onPostCreate()调用
onPostCreate() 如果Activity实例是第一次启动,则不调用,否则,以后的每次重新启动都会调用
onResume() Activity继续运行时
onSaveInstanceState(outState) 与onPause()相同,只是会先于onPause()调用
onPause() Activity暂停时被调用,导致暂停的原因除了onStop()中描述的四个原因外,还包括一个,即当用户长按Home键出现最近任务列表时,此时正在运行的Activity将被执行onPause()
onCreateDescription() 仅在要停止Activity时调用,先于onStop()
onStop() 一般会导致变为stop状态的原因有以下几个:用户按Back键,用户正在运行Activity时,按Home键,程序中调用finish()后,用户从A启动B后,A就会变为stop状态
onDestroy() 当Activity被销毁时,销毁的情况包括:当用户按下Back键后,程序中调用finish()后

按照AMS的调度过程重新总结以上回调函数在不同场合下的被调过程.

场合描述 回调过程
创建Activity对象并启动 onCreate();onStart();onRestoreInstanceState();onPostCreate();onResume()
Activity对象已经存在并继续运行 onStart();onResume()
Activity对象已经存在,并且满足上表中onNewIntent()的条件 onNewIntent();onStart();onResume()
AMS中调用startPausingLocked() onSaveInstanceState();onPause()
AMS空闲时调用stopActivityLocked() 如果没有暂停则先调用onSaveInstance();onPause();然后调用onCreateDescription();onStop()
AMS空闲时调用destroyActivityLocked() 如果没有暂停则先调用onSaveInstance();onPause();然后调用onCreateDescription();onStop();然后调用onDestroy()

ActivityThread初始化后,就进入Looper.loop()函数中无限循环,依靠消息机制运行,即当有消息处理时处理消息,而当没有消息时进程会进入到sleep状态.进程的状态显示为wait.ps命令查看进程的状态为S,也即sleep状态.

在Linux的内核调度中,如果一个线程的状态为sleep,除了占用调度本身的时间外,本身则不会占用CPU的时间片.

消息机制中,queue.next()方法可以被以下三种情况重新唤醒:

  • 定时器中断.如果应用程序中设置了定时器任务,那么当定时器发生时,操作系统会回调该定时器任务,程序员一般会在这个定时器任务中向looper主线程中发送一个消息,从而next()方法会被重新唤醒.
  • 用户按键消息.当有用户按键消息时,WMS中的专门处理输入消息的线程会吧这个消息发送到looper主线程,当点击屏幕时会从next()方法中跳出
  • Binder中断.Binder是Linux系统中的一个驱动设备,应用程序中可以包含一个Binder对象,该对象会在应用程序中自动创建一个相应的线程,当Binder驱动接收到Binder消息,并派发到客户端的Binder对象后,Binder线程会开始执行.如果在Binder线程中向looper主线程发送消息,next()会继续执行

在Android中运行了一个OOM进程,即Out of Memory.该进程启动时会首先向Linux内核中把自己注册为一个OOM Killer,即当Linux的内核的内存管理模块检测到系统内存低时就会通知已经注册的OOM进程,然后这些OOM Killer就可以根据各种规则进行内存释放了.Android中的OOM Killer进程是仅仅适用于Android应用程序的,该进程在运行时,AMS需要把每一个应用程序的oom_adj值告诉Killer.这个值的范围在-16到15,值越低,说明越重要,这个值类似于Linux系统中进程nice值,只是在标准的Linux中,有其自己的一套Killer机制.当发生内存低的条件时,Linux内核管理模块通知OOM Killer,Killer则根据AMS告知的优先级,强制退出优先级低的应用程序.

系统按照以下优先级关闭进程以释放内存.

  • 前台进程forground process,是指那些和用户正在做的事情相关的进程,具体包括:

    • 正在和用户交互的Activity,即该Activity的onResume()已经执行过

    • 包含一个service,该service正在服务于和用户交互的Activity

    • 包含一个service,该service正在执行onCreate(),或者onStart()或者onDestroy()

    • 包含一个BroadcastReceiver,正在执行onReceive()函数

  • 可视进程visible process,尽管没有和用户交互,但是却可以影响用户所能看得到的内容

    • 尽管没有包含和用户交互的Activity,但是用户却可以看得见该Activity的窗口,比如一个Activity上面弹出一个对话框的情况
    • 包含一个service,该service服务于可视的Activity,即上面说的看得见却不能交互的Activity
  • 服务进程service process,凡是使用startService()所启动的service对象,其所在的进程都称之为服务进程,如果service满足上面两个优先级中的条件,则会上升为相应的优先级

  • 后台进程backgroun process,不满足以上任何条件的进程,同时该进程中还包含一些不可见的Activity,这些进程不影响正在和用户交互的Activity

  • 空进程empty process,进程中不包含任何component,包括Activity,Service,Receiver对象.之所以还保留这些进程的原因是为了减少重新创建该进程的开销,创建一个空进程的开销包括创建进程本身,以及加载该应用中包含的resources.arsc资源文件,这些都是比较耗时的

results matching ""

    No results matching ""