我们在桌面上打开一个应用经历的流程
手机的桌面本质是一个Activity,是一个LauncherActivity。
public abstract class LauncherActivity extends ListActivity {
}
可以看到这个LauncherActivity 是继承自ListActivity,而ListActivity继承自Activity。
我们点击这些应用程序,启动应用程序,就是通过调用startActivity()方法。
每个应用都是一个单独的dalvik虚拟机,每一个应用都是一个单独的进程。桌面是一个Launcher进程。发送一个startActivity告诉ActivityManagerService(AMS)系统服务需要打开一个APP。打开APP需要知道包名和类名,就可以打开这个APP了。
ActivityManagerService就会通过Socket方式告诉Zygote进程,我需要开启新的进程,经过一系列的调用,就会fork一个进程出来,fork它自己的一个进程,这个进程就是我们的APP进程。
这个APP进程第一步就是创建一个Application线程出来,也是要去向ActivityManagerService请求的,告ActivityManagerService系统服务我需要一个ApplicationThread,经过一系列的方法调用,创建出了ApplicationThread以后,通过Handler方式会发送一个消息。之后就会进入Activity的生命周期。
Zygote进程:
在FramWork层中最重要的2个进程一个是SystemServer进程还有一个就是Zygote进程。开启进程就是通过Zygote分裂一遍的进程。只有和Zygote进程之间通信是通过Socket方式,其他进程之间的通信是用Binder方式,进程内部通信使用Handler方式。
SystemServer进程:
启动一些服务,ActivityMangerService、WindowManagerService、PackageManagerService 。这些就像一个服务器,我们的APP就像一个客户端,我们需要什么了,就向服务端请求。
如何创建一个进程
startActivity之后通过Binder方式告诉ActivityManagerService(AMS),ActivityManagerService负责系统中所有Activity的生命周期,告诉ActivityManagerService需要创建一个进程,AMS会调用Process.start,告诉Zygote进程需要创建一个新的进程,创建完以后就会调用ActivityThread.main()方法,一个APP的开始就开始于ActivityThread.main()方法。
一个APP的创建是从ActivityThread.main()开始的,我们看下main()的源码。
public static void main(String[] args) {
Looper.prepareMainLooper();
//开启消息队列循环
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
}
private void attach(boolean system, long startSeq) {
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
public final void bindApplication(...){
sendMessage(H.BIND_APPLICATION, data);
}
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
private void handleBindApplication(AppBindData data) {
app = packageInfo.makeApplication(false, mInstrumentation);
context = (ContextImpl) app.getBaseContext();
}
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
try {
java.lang.ClassLoader cl = getClassLoader();
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {...}
mActivityThread.mAllApplications.add(app);
mApplication = app;
}
创建Application的核心代码:
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;
}
只要知道一个包名和MainActivity就可以打开一个Activivity。这里用到了反射机制去获得一个Application。
可以看到attach()方法比onCreate方法先执行。
整个流程可以概括如下:
1、点击桌面应用图标,Launcher 进程将启动Activity(MainActivity)的请求以Binder 的方式发送给了AMS。
2、AMS 接收到启动请求后,交付ActivityStarter 处理Intent 和Flag 等信息,然后再交给ActivityStackSupervisior/ActivityStack 处理Activity 进栈相关流程。同时以Socket 方式请求Zygote 进程fork 新进程。
3、Zygote 接收到新进程创建请求后fork 出新进程。
4、在新进程里创建ActivityThread 对象,新创建的进程就是应用的主线程,在主线程里开启Looper 消息循环,开始处理创建Activity。
5、ActivityThread 利用ClassLoader 去加载Activity、创建Activity 实例,并回调Activity 的onCreate()方法,这样便完成了Activity 的启动。
再看看另一幅启动流程图来加深理解:
本文地址:https://blog.csdn.net/jingerlovexiaojie/article/details/108979591
上一篇: 钉钉一个手机号可以进两个班级吗 一个手机号进两个班级教程
下一篇: GreenDao配置及使用