本文主要总结梳理一下,应用进程启动, 以及应用中各种Context那些事儿,如有错误,欢迎指出~
一,应用进程创建
1,zygote创建新进程
Android 应用程序不能主动开启一个进程,只能被动开启进程。在Mainfest注册四大组件时,可以指定运行的进程。在启动该组件时,AMS首先会判断该进程 是否已存在,如果不存在,则首先请求zygote进程创建该进程。
以启动一个服务为例,程序会先调用ActivityManagerService 中的startService()方法,在该方法内部会调用到ActiveService的bringUpServiceLocked方法 启动服务。
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
......
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
}
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
bringDownServiceLocked(r);
return msg;
}
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
return null;
}
mAm.getProcessRecordLocked()方法 用于判断当前进程是否已经存在,若不存在,则调用ActivityManagerService的startProcessLocked方法创建一个进程。最终会调用到Process的start方法。会请求zygote进程创建一个进程。
public static final ProcessStartResult start(...) {
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
ZygoteProcess封装了与zygote进程相关的socket通信。zygote进程创建一个新进程后,会将该新进程的pid 返回当前系统进程中。
@GuardedBy("mLock")
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList args)
throws ZygoteStartFailedEx {
try {
......
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
2,新进程向AMS发布IBinder实体对象
新进程启动后,首先会执行ActivityThread.main函数,在 thread.attach()方法中会通过Binder机制调用AMS的attachApplication方法,实际上就是通知AMS 新进程已创建好,并将自己的IBinder发布到AMS中。
public static void main(String[] args) {
.....
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
.....
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
.....
}
3,创建新进程Application对象
当应用进程启动,并向AMS发布自己的IBinder实体对象后,AMS 调用attachApplication()方法创建应用的Application对象。其中,thread为应用进程在AMS进程的binder对象。
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
}
}
@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
.....
thread.bindApplication(...)
......
return true;
}
bindApplication()方法在应用进程的Binder线程中执行。 首先会封装app数据到AppBindData,然后发送Handler消息,在主线程中执行handleBindApplication()方法。
public final void bindApplication(...) {
AppBindData data = new AppBindData();
.....
sendMessage(H.BIND_APPLICATION, data);
}
public void handleMessage(Message msg) {
switch (msg.what) {
case BIND_APPLICATION:
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
break;
private void handleBindApplication(AppBindData data) {
//初始化应用程序 基本数据
......
Application app;
//创建Appcalition对象
app = data.info.makeApplication(data.restrictedBackupMode, null);
......
//调用Application.onCreate()方法
mInstrumentation.callApplicationOnCreate(app);
......
}
通过调用Instrumentation 中的newApplication()方法,通过反射创建Application对象,并调用
Application.attach(Context)生命周期回调方法
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
app.attach(context);
return app;
}
至此完成Application的创建工作,由此也可得出,Application并不是与应用相对应,而是与应用进程一一对应。
4,创建service实例
AMS最终会同过Binder机制通知 刚刚创建的进程创建服务类实例,并调用服务相关的生命周期函数。
private void handleCreateService(CreateServiceData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
}
二,各种Context
1,简介
Context是提供应用程序上下文的一个抽象类,可以用来访问系统资源,系统服务等等。
public abstract class Context {
public abstract Resources getResources();
public abstract Context getApplicationContext();
public abstract String getSystemServiceName(Class> serviceClass);
public abstract void startActivity( Intent intent);
public abstract ComponentName startService(Intent service);
}
ContextWrapper 是Context的实现类,同时接收一个ContextImp 对象 做静态代理。
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
public Context getBaseContext() {
return mBase;
}
...
}
ContextImpl 实现Context, 完成具体操作
class ContextImpl extends Context {
....
}
2, Application 中的Context
Applicaiton继承ContextWrapper, 具有保存应用进程内的全局变量、初始化操作、提供应用上下文的作用。
public class Application extends ContextWrapper implements ComponentCallbacks2 {
...
public Application() {
super(null);
}
final void attach(Context context) {
attachBaseContext(context);
}
public void onCreate() {
}
}
应用程序创建Application, 并创建ContextImp对象通过attch赋值给mBase
public Application makeApplication(...){
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
}
public Application newApplication(ClassLoader cl, String className, Context context) {
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
app.attach(context);
return app;
}
3, Activity 中的Context
Activity继承ContextThemeWrapper类,而 ContextThemeWrapper继承ContextWrapper,只是封装了主题相关内容。
public class Activity extends ContextThemeWrapper{
......
public final Application getApplication() {
return mApplication;
}
final void attach(...) {
attachBaseContext(context);
mApplication = application;
}
}
应用程序创建Activity
private Activity performLaunchActivity(...){
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
}
4, Service 中的Context
Service继承ContextWrapper .
public abstract class Service extends ContextWrapper {
public final void attach(...) {
attachBaseContext(context);
mApplication = application;
}
public final Application getApplication() {
return mApplication;
}
}
创建Service
private void handleCreateService(CreateServiceData data) {
service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
}
5,各种获取Context方法比较
在Activity 或Service中,都可以使用以下三种方法取得Context, 但无论是Application、Activity或Service中,实际发挥作用的都是baseContext中的 ContextImp对象。
//获取对象是 当前Activity 或Service 本身,慎用,可能会引起内存泄漏
Context context = this;
//获取对象是 当前Activity 或Service中的mBase, 即ContextImpl实例
Context baseContext = getBaseContext();
//以下两种方法获取的都是当前应用的Application对象, 可以放心使用
Application application = getApplication();
Context applicationContext = getApplicationContext();
完~