por*_*der 3 java android android-lifecycle
我已经实现了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
}
Run Code Online (Sandbox Code Playgroud)
我有一个应用程序类,它从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");
}
Run Code Online (Sandbox Code Playgroud)
我的主要活动只是跟踪生命周期。一切正常。我的生命周期方法如下所示:
@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();
}
Run Code Online (Sandbox Code Playgroud)
我缺少什么来调用onTrimMemory()?
如果您查看有关的文档ComponentCallbacks2,将会发现它已经在Application和类上实现了Activity。因此,对于这些组件,我们欢迎您重写onTrimMemory(),并将在适当时调用它。
这应该允许您从问题中删除几乎所有代码。
也许这对其他人来说是显而易见的,但对我来说,我在没有澄清这一点的答案上浪费了很多时间:当整个系统(而不是专门针对您的应用程序)低时调用 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.
}
Run Code Online (Sandbox Code Playgroud)
TotalFreeMem 需要进行该计算,因为totalMemory() 只是当前分配给JVM 的内存总量,该总量可能小于允许的maxMemory()。freeMemory() 是当前分配的内存中的可用内存量,而不是在允许的最大值内。
不幸的是,这意味着没有自动回调方法可以知道您的 JVM 内存何时不足(据我所知),因此您需要在代码的各个部分进行低内存检查,您知道内存经常被消耗,并且酌情释放它。
当然,您也可能会遇到系统性能较低但应用程序的 JVM 性能较低的情况,因此您仍然希望实现 onTrimMemory 并酌情释放内存。尽管我认为这种情况很少见,因为您的 JVM 拥有足够的内存,并且系统认为内存总体较低。