onLowMemory方法顾名思义就是在app内存低的时候回调,那么怎样才是内存低的标准,回调流程又是如何?我们一起带着问题去看源代码解析。
onLowMemory方法在Activity,Servier,ContentProvider,Application中都有回调,但是BroadcastReceiver没有这个回调。
MemBinder是一个Binder类型的服务,主要用于检测系统内存情况;
当系统可用内存比较低的时候就会执行了该方法,然后回调到ActivityManagerService中的killAllBackground方法
可以发现最终通过一个Handler类型的mH成员变量发送一个异步消息,这样异步消息最终会被mH的handleMessage方法执行。。。。,经过查看源代码我们知道在mH的handleMessage方法中最终调用的是handleLowMemory方法
final void handleLowMemory() {
ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
final int N = callbacks.size();
for (int i=0; i<N; i++) {
callbacks.get(i).onLowMemory();
}
// Ask SQLite to free up as much memory as it can, mostly from its page caches.
if (Process.myUid() != Process.SYSTEM_UID) {
int sqliteReleased = SQLiteDatabase.releaseMemory();
EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
}
// Ask graphics to free up as much as possible (font/image caches)
Canvas.freeCaches();
// Ask text layout engine to free also as much as possible
Canvas.freeTextLayoutCaches();
BinderInternal.forceGc("mem");
}
可以发现这里通过遍历ComponentCallbacks2并执行了其onLowMemory方法,那么这里的ComponentCallBacks2是什么呢?这里我们查看一下collectComponentCallbacks方法的实现逻辑。
ArrayList<ComponentCallbacks2> collectComponentCallbacks(
boolean allActivities, Configuration newConfig) {
ArrayList<ComponentCallbacks2> callbacks
= new ArrayList<ComponentCallbacks2>();
synchronized (mResourcesManager) {
final int NAPP = mAllApplications.size();
for (int i=0; i<NAPP; i++) {
callbacks.add(mAllApplications.get(i));
}
final int NACT = mActivities.size();
for (int i=0; i<NACT; i++) {
ActivityClientRecord ar = mActivities.valueAt(i);
Activity a = ar.activity;
if (a != null) {
Configuration thisConfig = applyConfigCompatMainThread(
mCurDefaultDisplayDpi, newConfig,
ar.packageInfo.getCompatibilityInfo());
if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
// If the activity is currently resumed, its configuration
// needs to change right now.
callbacks.add(a);
} else if (thisConfig != null) {
// Otherwise, we will tell it about the change
// the next time it is resumed or shown. Note that
// the activity manager may, before then, decide the
// activity needs to be destroyed to handle its new
// configuration.
if (DEBUG_CONFIGURATION) {
Slog.v(TAG, "Setting activity "
+ ar.activityInfo.name + " newConfig=" + thisConfig);
}
ar.newConfig = thisConfig;
}
}
}
final int NSVC = mServices.size();
for (int i=0; i<NSVC; i++) {
callbacks.add(mServices.valueAt(i));
}
}
synchronized (mProviderMap) {
final int NPRV = mLocalProviders.size();
for (int i=0; i<NPRV; i++) {
callbacks.add(mLocalProviders.valueAt(i).mLocalProvider);
}
}
return callbacks;
}
可以发现该方法最终返回类型为ArrayList类型的callBacks而我们的callBacks中保存的是我们应用进程中的Activity,Service,Provider以及Application等。Activity,Service,Provider,Application都是ComponentCallBacks2类型的么?我们看一看一下具体的定义:
Activity的定义:
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback
Service的类定义:
public abstract class Service extends ContextWrapper implements ComponentCallbacks2
ContentProvider的类定义:
public abstract class ContentProvider implements ComponentCallbacks2
Application的类定义:
public class Application extends ContextWrapper implements ComponentCallbacks2
可以发现其都是继承与ComponentCalbacks2,所以其都可以被当做是ComponentCallbacks2类型的变量。而同样是四大组件的BroadcastReceiver,我们可以下其类定义:
public abstract class BroadcastReceiver
可以看到其并未继承与ComponentCallbacks2,所以并未执行,所以通过这样的分析,我们知道了,最终应用程序中的Activity,Servier,ContentProvider,Application的onLowMemory方法会被执行。而由于我们是在系统内存紧张的时候会执行killAllBackground方法进而通过层层条用执行Activity、Service、ContentProvider、Application的onLowMemory方法,所以我们可以在这些组件的onLowMemory方法中执行了一些清理资源的操作,释放一些内存,尽量保证自身的应用进程不被杀死。
总结:
系统在JNI层会时时检测内存变量,当内存过低时会通过kiilbackground的方法清理后台进程。
经过层层的调用过程最终会执行Activity、Service、ContentProvider、Application的onLowMemory方法。
可以在组件的onLowMemory方法中执行一些清理资源的操作,释放内存防止进程被杀死。