读Android源码-冷启动时的ActivityThread
前言:
应用冷启动时需要创建进程,开启主线程,实例化应用所需组件。
读ActivityThread源码有助于我们了解这个过程中,客户端做的那些事。
冷启动创建应用时,ActivityThread的主要方法:
- main()
-- 1. 开启消息循环
-- 2. 通知ActivityManagerService
-- 3. 添加GCWatcher- handleBindApplication()
-- 1. 创建LoadedApk
-- 2. 创建Instrumentation
-- 3. 创建Application
-- 4. 通过Instrumentation调用Application的onCreate()方法
main()
main方法是一个应用创建的入口,他主要做了3件事
1. 开启消息循环
调用Looper.prepareLoop() Looper.loop(),开启主线程的消息循环,以便于ApplicationThread调用ActivityThread中的生命周期方法。
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
...
Looper.loop();
}
2. 通知ActivityManagerService
调用ActivityThread.attach()方法,attach()方法在调用了attachApplication()将ApplicationThread这个Binder交给了ActivityManagerService,意味着ActivityManagerService可以通过ApplicationThread控制我们的应用,建立了服务器端对客户端的通信渠道。
private void attach(boolean system){
...
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
}
SDK26以后,去除了Native和Proxy,而是直接从ActivityManager(ServiceManager)中获取ActivityManagerService的Binder对象进行通信
3. 添加GCWatcher
在attach()方法中,添加了监听dialvik内存使用情况得监听者GcWatcher,当内存使用超过总容量的3/4,则打印Log进行记录,并且调用ActivityManagerService的releaseSomeActivities()进行内存释放操作,以防止内存溢出导致应用崩溃。
private void attach(boolean system){
...
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
if (dalvikUsed > ((3*dalvikMax)/4)) {
if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
+ " total=" + (runtime.totalMemory()/1024)
+ " used=" + (dalvikUsed/1024));
mSomeActivitiesChanged = false;
try {
mgr.releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
});
...
}
handleBindApplication()
ActivityManagerService=AMS
handleBindApplication的被调用时机是:
- 通过上面AMS.attachApplication()后,AMS获得了控制应用的Binder对象ApplicationThread。
- AMS进行了一系列操作后(这里先省略),调用了ApplicationThread的bindApplication()
- bindApplication中通过消息机制,sendMessage到ActivityThread,调用了ActivityThread的handleBindApplication()
handleBindApplication是创建用于所需组件的入口,他主要做了4件事:
1. 创建LoadedApk
LoadedApk对象包含应用的所有信息
private void handleBindApplication(AppBindData data){
...
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
...
}
2. 创建Instrumentation
Instrumentation是应用组件的管家,组件的生命周期方法都需要通过它来调用,是客户端与服务器端通信的最后一步。
private void handleBindApplication(AppBindData data){
...
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}
...
}
3. 创建Application
调用了LoadedApk.makeApplication()进行Application的创建
private void handleBindApplication(AppBindData data){
...
app = data.info.makeApplication(data.restrictedBackupMode, null);
...
}
- 先通过ContextImpl.createAppContext()获得Application的Context
- 再通过Instrumentation.newApplication(),用ClassLoder创建Applicaition
- 创建后Applicaition调用自身的attach(Context)方法,将Context与Applicaition绑定,完成创建
LoadedApk.class
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
...
Application app = null;
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
...
return app;
}
4. 通过Instrumentation调用Application的onCreate()方法
private void handleBindApplication(AppBindData data){
...
mInstrumentation.callApplicationOnCreate(app);
...
}
更新中...