Android 如何在内存不足时释放内存,以及如何重新启动它们?

How does Android go about freeing up memory when low, and how does it restart them?

请注意以下词汇,以免混淆

1) 当我说 重新实例化 一个 activity 时,我的意思是 Activity.onCreate(bundle)

2) 当我说 从头开始​​ 和 activity 时,我的意思是 Activity.onCreate(null)

(虽然我不确定这有什么不同)为了这个 post 的目的,请假设我感兴趣的 Android 应用程序都有他们的活动在同一任务中启动

Android 如何从应用程序中释放内存?

假设我有一个 phone。我同时使用了很多应用程序。我厌倦了当前的 Snapchat 应用程序。所以我按下主页按钮并打开 Facebook请注意,我没有按后退按钮,因此 Snapchat 在最近的应用程序概览中继续存在

突然由于某种原因 phone 内存非常低,需要开始从后台应用程序中强制释放一些内存。

Android 如何管理 "killed" 应用程序?

现在假设我想回到 Snapchat。我点击了概述按钮,然后从最近使用的应用程序的滚动列表中点击 select Snapchat

TL;DRD:所有活动都被杀死。

ActivityManagerService 似乎不再杀死任何东西(它只是强制 GC 调用并调度 trim 事件)。

if (false) {
   // For now we won't do this; our memory trimming seems
   // to be good enough at this point that destroying
   // activities causes more harm than good.
   if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE 
            && app != mHomeProcess && app != mPreviousProcess) {
       // Need to do this on its own message because the stack may not
       // be in a consistent state at this point.
       // For these apps we will also finish their activities
       // to help them free memory.
       mStackSupervisor.scheduleDestroyAllActivities(app, "trim");
   }
 }

虽然当(如果)它确实试图杀死某些东西时它会杀死后台应用程序的整个进程(它只会调用 kill -9 [PID])。由于默认情况下您的所有活动都 运行 在一个 PID 下,当进程终止时,它们都会被销毁。

OOM 和 Low Memory Killers 也是如此 - 两者与进程一起运行并且不区分您的活动。

但是请注意,有些人声称 Android 有时会在内存不足时一项一项地终止特定活动。我没能在 AOSP.

中找到任何证据

==============
现在,关于恢复您的应用程序。我可能不是这里的专家,因为这与 Android 的 "Tasks and Back Stack System" 有关,这比他们的教程视频看起来要复杂得多。

操作从调用 ActivityManager#moveTaskToFront(...) 开始,最终将我们带到 ActivityManagerService#moveTaskToFrontLocked(...)

那里 OS 将尝试检索与您的应用关联的已存储任务记录。如果您的应用程序已被销毁,管理器将不得不转到 ActivityStackSupervisor#restoreRecentTaskLocked(...),如果一切顺利,它将找到任务和返回堆栈,并对任务中的每个 activity 执行此操作:

final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
   final ActivityRecord r = activities.get(activityNdx);
   mWindowManager.addAppToken(0, r.appToken, task.taskId, stack.mStackId,
     r.info.screenOrientation, r.fullscreen,
    (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
       r.userId, r.info.configChanges, task.voiceSession != null,
      r.mLaunchTaskBehind);
}

当您开始一个新的 activity 时调用相同的方法 (WindowManager#addAppToken(...)) 并且它带有注释:

// Here it is!  Now, if this is not yet visible to the
// user, then just add it without starting; it will
// get started when the user navigates back to it.

所以我的猜测是,当OS恢复一个应用程序时,它会完全重新创建activity堆栈,但实际上只有最顶层的activity实际上会重新启动。我想,设置一个实验来确定我是否就在这里很容易。

=======
又一次更新 :) 是的,这两个方法(ActivityStackSupervisor#resumeTopActivitiesLocked()ActivityStackSupervisor#resumeTopActivityLocked(...))稍后会被调用。虽然我真的不理解为什么他们在多个堆栈中恢复活动 - 正如我所说,我绝对不是这里的专家。