繁体   English   中英

ComponentCallbacks2 中的 onTrimMemory() 没有被调用

[英]onTrimMemory() from ComponentCallbacks2 does not get called

我已经实现了 ComponentCallbacks2 并且 onTrimMemory 永远不会被调用。 我正在尝试使用 Application 类和我的自定义生命周期来管理内存。 对此的任何帮助表示赞赏。

public class MemoryManager implements ComponentCallbacks2 {
    private static List<MemoryInfo> memInfoList = new ArrayList<>();

    public interface MemoryInfo {
        void releaseMemory();
    }

    public static void registerMemoryListener(MemoryInfo memoryInfo) {
        memInfoList.add(memoryInfo);
    }

    public static void unregisterMemoryListener(MemoryInfo memoryInfo) {
        memInfoList.remove(memoryInfo);
    }

    @Override
    public void onTrimMemory(int level) {
        Log.i("TEST", "onTrimMemory called"); // does not get called
        switch (level) {
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
                try {
                    for (int i = memInfoList.size() - 1; i >= 0; i--) {
                        try {
                            memInfoList.get(i).releaseMemory(); // is this correct implementation?
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
                // I added logs here, it does not get reached
                break;
            default:
                break;
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        // do nothing
    }

    @Override
    public void onLowMemory() {
        // will log when there is log memory
    }

我有一个从 MemoryManager 类调用我的接口的应用程序类。

public class TestApplication extends Application implements ActivityLifecycleCallback, MemoryManager.MemoryInfo {

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onStart(Activity activity) {
        Log.i(TAG, "onStart() called :: " + activity.getLocalClassName());
    }

    @Override
    public void onResume(Activity activity) {
        Log.i(TAG, "onResume called :: " + activity.getLocalClassName());
        MemoryManager.registerMemoryListener(this);
    }

    @Override
    public void onPause(Activity activity) {
        Log.i(TAG, "onPause called :: " + activity.getLocalClassName());
    }

    @Override
    public void onStop(Activity activity) {
        Log.i(TAG, "onStop called :: " + activity.getLocalClassName());
        MemoryManager.unregisterMemoryListener(this);
    }

    @Override
    public void onDestroy(Activity activity) {
        Log.i(TAG, "onDestroy called :: " + activity.getLocalClassName());
    }

    @Override
    public void releaseMemory() {
        Log.i(TAG, "releaseMemory() called");
    }

我的主要活动只是跟踪生命周期。 这工作正常。 我的生命周期方法如下所示:

@Override
protected void onDestroy() {
    // register lifecycle
    application.onDestroy(activity);
    super.onDestroy();
}

@Override
protected void onPause() {
    // register lifecycle
    application.onPause(activity);
    super.onPause();
}

@Override
protected void onResume() {
    // register lifecycle
    application.onResume(activity);
    super.onResume();
}

@Override
protected void onStart() {
    // register lifecycle
    application.onStart(activity);
    super.onStart();
}

调用 onTrimMemory() 缺少什么?

如果您查看ComponentCallbacks2的文档,您会注意到它已经在ApplicationActivity等类上实现。 因此,对于这些组件,欢迎您只覆盖onTrimMemory() ,它会被适当调用。

这应该允许您从问题中删除几乎所有代码。

你不应该实现ComponentCallbacks2 ,如果想使用onTrimMemory() ,你应该在你的 Application 类中覆盖onTrimMemory() 但是,如果您真的想在自定义类中正确使用它,请使用registerComponentCallbacks(ComponentCallbacks callback)

您可以使用registerActivityLifecycleCallbacks(callback); 如果您想开始跟踪您的活动生命周期。

其中回调是实现Application.ActivityLifecycleCallbacks程序类

例如,您可以在 Application 类的 OnCreate 方法中注册它。

也许这对其他人来说是显而易见的,但对我来说,我在没有澄清这一点的答案上浪费了很多时间:当整个 SYSTEM 低时调用 onTrimMemory,而不是专门的应用程序。 好吧,当您的应用程序进入后台以释放 UI 资源时也会调用它,但这与本讨论无关。

您的应用程序可能会在系统认为自己整体较低之前耗尽分配给其 JVM 的内存。

要确定您的应用程序是否内存不足,您需要查看 JVM 的内存分配。 这很简单:

long maxMem = Runtime.getRuntime().maxMemory();
long totalMem = Runtime.getRuntime().totalMemory();
long freeMem = Runtime.getRuntime().freeMemory();
long totalFreeMem = maxMem - totalMem + freeMem;

if (totalFreeMem < (maxMem * 0.2f)) {
    // I'm using 20% as my threshold for "low memory".  Use a value appropriate for your application.
}

totalFreeMem 需要该计算,因为 totalMemory() 只是当前分配给 JVM 的内存总量,可能小于它允许的 maxMemory()。 而 freeMemory() 是当前分配的内存中的空闲内存量,而不是允许的最大值。

不幸的是,这意味着没有自动回调方法来知道您的 JVM 何时内存不足(我知道),因此您需要在代码的各个部分进行低内存检查,其中您知道内存经常被消耗并且适当地释放它。

当然,您也可以遇到系统低但应用程序的 JVM 不低的情况,因此您仍然希望适当地实现 onTrimMemory 和释放内存。 虽然我认为这对于您的 JVM 拥有充足内存并且系统认为它总体上较低是一种罕见的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM