【问题标题】:Detect whether application is quit by the OS because of low RAM检测应用程序是否因 RAM 不足而被操作系统退出
【发布时间】:2023-03-08 19:37:01
【问题描述】:

在我正在构建的应用程序中,当且仅当应用程序在后台退出时,我需要检测应用程序退出,因为操作系统正在回收内存。

根据我自己的实验,在每个实例上都会调用 onDestroy。我试过检查 isFinishing 但我不能 100% 确定这会将它隔离到哪些情况。

@Override
public void onDestroy()
{
    super.onDestroy();
    Log.i("V LIFECYCLE", "onDestroy");
    if (!isFinishing())
    {
        // are we here because the OS shut it down because of low memory?
        ApplicationPreferences pref = new ApplicationPreferences(this);
        // set persistant flag so we know next time that the user
        // initiated the kill either by a direct kill or device restart.
        pref.setThePersistantFlag(true);
        Log.i("DEBUG", "onDestroy - ensuring that the next launch will result in a log out..");
    }
}

谁能在这里阐明我的问题?谢谢。

【问题讨论】:

    标签: android memory-management


    【解决方案1】:

    不知道对你有没有帮助,

    来自Android Activity类,

    public void onLowMemory ()
    

    当整个系统的内存不足时调用,并且希望积极运行的进程试图勒紧裤腰带。虽然没有定义调用它的确切时间,但通常它会在所有后台进程都被杀死的时候发生,即在到达我们希望避免杀死的托管服务和前台 UI 的进程终止点之前。

    想要变得更好的应用程序可以实现此方法来释放它们可能持有的任何缓存或其他不必要的资源。从这个方法返回后系统会为你执行一次gc。

    自:API 级别 14

    public abstract void onTrimMemory (int level)
    

    当操作系统确定现在是进程从其进程中删除不需要的内存的好时机时调用。例如,当它进入后台并且没有足够的内存来保持尽可能多的后台进程运行时,就会发生这种情况。您永远不应该与级别的确切值进行比较,因为可能会添加新的中间值——您通常希望比较该值是否大于或等于您感兴趣的级别。

    【讨论】:

    • 我试过了,除非应用程序在前台,否则不会调用 onLowMemory()。我需要捕获操作系统由于内存不足而关闭设备的时间。 OnTrimMemory 听起来很有希望,但它只有 4.0 及更高版本,我们需要支持 2.2 及更高版本的设备。您能否对 isFinishing() 和 onDestroy() 方法有所了解?是否有两种组合可以检测到操作系统因内存不足而将其关闭?也许是一种在调用 onDestroy 时检查操作系统是否处于低内存状态的方法?
    • 我重新表述了我的问题,以便于理解。
    • 我解决了。不过,感谢您的回答-如果旧 API 中只有 onTrimMemory(level) 就好了!
    【解决方案2】:

    通过反复试验,我制定了一个非常适合任何感兴趣的人的解决方案。在操作系统回收内存的情况下,我已经缩小了应用程序状态恢复 (onResume) 的情况。

    public boolean wasJustCollectedByTheOS = false; 
    
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState)
    {
        super.onSaveInstanceState(savedInstanceState);
        // this flag will only be present as long as the task isn't physically killed
        // and/or the phone is not restarted.
        savedInstanceState.putLong("semiPersistantFlag", 2L);
    }
    
    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        long semiPersistantFlag = savedInstanceState.getLong("semiPersistantFlag");
        if (semiPersistantFlag == 2L)
        {
            savedInstanceState.putLong("semiPersistantFlag", 0L);
            this.wasJustCollectedByTheOS = true;   
        }
    }
    
    // this gets called immediately after onRestoreInstanceState
    @Override
    public void onResume() {
        if (this.wasJustCollectedByTheOS){
            this.wasJustCollectedByTheOS = false;
            // here is the case when the resume is after an OS memory collection    
        }
    }
    

    【讨论】:

    • 它对我不起作用。我刚刚旋转了我的手机,上面的代码告诉这是因为操作系统内存收集。
    猜你喜欢
    • 2020-03-15
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多