Android AMS源码分析阅读(三)

Activity 之stop过程

在之前学习了AMS如何与客户进程进行交互,从而实现启动应用进程并且创建application以及activity,调用activity生命周期进行界面显示的过程。那么当activity显示了之后,如何停止呢?现在就来学习一下,activity停止有很多种情况,例如从A启动B,那么A需要通知,又或者点击了Home键、返回键等,但是其实最终都是会经过startActivity()这一步。

Android内部提出了一种主动内存管理机制,即AMS会根据当前activity的状态,在系统内存不够用的时候杀死优先级较低的应用以释放内存空间。如何判断优先级的高低呢?就需要给不同的activity赋予不同的权值了,这个权值指的就是Activity的状态,包括正在运行、停止、销毁等,相应activity的几个回调(onPause()、onStop()、onDestroy()),不同的回调时机不同,例如当暂停和用户交互时,回调onPause(),当AMS希望把activity的权值改为stop状态时,回调onStop(),若要杀死activity,则回调onDestroy().

前面在执行handleResumeActivity()时,在最后添加了一个Idler对象;

public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
 ....         
 Looper.myQueue().addIdleHandler(new Idler());

Idler内部是调用AMS的activityIdle(),经过一系列的调用,最终会来到ActivityStack的stopActivityLock(),代码如下:

final void stopActivityLocked(ActivityRecord r) {
       
        /**
          * 1.处理FLAG_ACTIVITY_NO_HISTORY标识,这个标识的作用是不要让该activity出现在
          * mHistory中,如果该activity就要让它finish。比如A -> B -> C,如果B的启动标识包含了
          * 该标识,那么要把B finish了,从C返回的是A,而不是B。
          **/
        if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
            if (!r.finishing) {
                if (!shouldSleepActivities()) {
                  
                    if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                            "stop-no-history", false)) {
                        
                        r.resumeKeyDispatchingLocked();
                        return;
                    }
                } 
            }
        }
		 
        if (r.app != null && r.app.thread != null) {
            adjustFocusedActivityStack(r, "stopActivity");
            r.resumeKeyDispatchingLocked();
            try {
                r.stopped = false;
                
                r.setState(STOPPING, "stopActivityLocked");
                
                /**
                  * 2.设置目标activity隐藏
                  **/
                if (!r.visible) {
                    r.setVisible(false);
                }
                EventLogTags.writeAmStopActivity(
                        r.userId, System.identityHashCode(r), r.shortComponentName);
                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
                        StopActivityItem.obtain(r.visible, r.configChangeFlags));
                if (shouldSleepOrShutDownActivities()) {
                    r.setSleeping(true);
                }
                /**
                  * 3.向目标进程的ActivityThread发送一个消息,通知它去停止指定的activity
                  **/
                Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
                mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
            } catch (Exception e) {
                
                r.stopped = true;
             
                r.setState(STOPPED, "stopActivityLocked");
                if (r.deferRelaunchUntilPaused) {
                    destroyActivityLocked(r, true, "stop-except");
                }
            }
        }
    }

执行完上面的过程之后,ActivityThread的handleStopActivity()将开始执行,代码如下:

public void handleStopActivity(IBinder token,...) {
        final ActivityClientRecord r = mActivities.get(token);
        r.activity.mConfigChangeFlags |= configChanges;

        final StopInfo stopInfo = new StopInfo();
        
        /**
          * 1.调用performStopActivityInner(),这个方法内部主要做几件事情
          *   1.1 调用performPauseActivityIfNeeded()回调activity的onPause(),activity在stop之前必须pause,同时将状态改为pause
          *   1.2 判断info是否为空,不为空则回调onCreateDescription(),产生对该Activity的描述,AMS可能需要该描述进行一定的统计
          *   1.3 回调Activity的onStop()方法
          *   
          **/
        performStopActivityInner(r, stopInfo, show, true /* saveState */, finalStateRequest,
                reason);

        /**
          * 2.这里将该Activity的窗口即DecorView设置为隐藏
          **/
        updateVisibility(r, show);


		  /**
		    * 3.调用AMS的ActivityStop(),向AMS报告,自己已经停止了该Activity,AMS内部会调用trimApplication()进行一定的内存回收工作
		    **/        
        if (!r.isPreHoneycomb()) {
            QueuedWork.waitToFinish();
        }
		 
        stopInfo.setActivity(r);
        stopInfo.setState(r.state);
        stopInfo.setPersistentState(r.persistentState);
        pendingActions.setStopInfo(stopInfo);
        mSomeActivitiesChanged = true;
    }

pause和stop的过程大致如图:
《Android AMS源码分析阅读(三)》

Android内存与Linux配合进行内存管理

android的内存管理分成两部分,第一部分是应用程序关闭后,后台进程没有真正提出,以便下次能够快速启动;第二部分是,当系统内存不够用时,AMS会主动根据一定的优先规则退出优先级较低的进程。何为内存不够用呢,这是属于Linux内核的内存管理控制的事情,AMS是无法预知的,应用程序和AMS运行在两个独立的虚拟机中,应用程序申请内存不会告知AMS,AMS无法感知应用程序申请内存的状况。那么Linux和AMS是如何联系到一起呢?以及AMS如何得知内存不够用呢?

看下这个详细的图:
《Android AMS源码分析阅读(三)》

Android的OOM killer进程会想Linux内核注册内存管理模块,AMS中会设置进程的oom_adj值,标识着该进程的优先级,当Linux内核发现内存不够时,就会通知OOM killer,然后OOM killer从AMS中获取各个进程的oom_adj值,将值大的进程有选择性的杀死,可见,AMS在这个内存回收和进程管理的角色更像是一个信息的提供着,真正进行回收的并非是AMS,它只是负责提供进程的信息,最后是由OOM killer去执行清理以及回收的工作。

    原文作者:小毕加猪
    原文地址: https://blog.csdn.net/qq_26984087/article/details/86601120
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞