我是靠谱客的博主 灵巧万宝路,最近开发中收集的这篇文章主要介绍Activity启动流程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

         这篇文章用到了Android系统源码,大家可以从这个网站方便的查询:https://cs.android.com/,这个网站需要科学上网,下面有些文字是超链接,点击能直接看源码。

Launcher

简述

        Launcher即是Android的桌面应用,它与一般的应用并没有本质的区别。不过它有几个特点,一是常驻系统,按home键之后或者退出其他应用之后会回到Launcher,二是通过PackageManager来获取系统中的的应用的图标,名称等信息,并且用GirdView等布局展示出来。

        应用启动的信息保存在应用View的Tag里面,点击的时候会获取应用在Manifest文件中注册的信息,然后构建intent来启动应用的首页activity,下面是源码。

源码

public void onClick(View v) {
......
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
onClickAppShortcut(v);
}
.....
}
protected void onClickAppShortcut(final View v) {
....
// Start activities
startAppShortcutOrInfoActivity(v);
}
private void startAppShortcutOrInfoActivity(View v) {
ItemInfo item = (ItemInfo) v.getTag();
Intent intent;
if (item instanceof PromiseAppInfo) {
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
intent = promiseAppInfo.getMarketIntent();
} else {
intent = item.getIntent();
}
boolean success = startActivitySafely(v, intent, item);
....
}
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
......
// Prepare intent
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
......
// Could be launching some bookkeeping activity
startActivity(intent, optsBundle);
......
}

        可以看出来,最终还是调用了最常用的startActivity方法来启动应用。

startActivity阶段

简述

        启动Activity需要通过AMS(ActivityManagerService)完成,因此在startActivity系列方法中就需要获取AMS。

public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
Uri referrer = onProvideReferrer();
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, who, requestCode,
ar.getResultCode(), ar.getResultData());
}
cancelInputsAndStartExitTransition(options);
}

         这是Activity的startAcivity方法,从这里可以看出,启动activity的任务先是被交给了一个Instrumentation的实例(即mInstrumentation)完成,参数的话传入了这个原先Activity的context,主线程,启动目标,启动的intent等。

public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};

        这一段看了半天才明白是干啥,这块的目的是获取ActivityTaskManager属于Android系统的类,在这个类里面最终会调用ActivityManagerService的启动Activity方法。 

        具体是怎么获取的呢,那个Singleton<IActivityTaskManager>是个单例,这里重写了它的create方法,第一次获取的时候会调用create方法,之后会直接get获取,创建单例的时候先通过ServiceManager的getService方法获取Binder对象,再向系统服务进程获取IActivityTaskManager。

AMS启动进程阶段

        这个阶段的主要任务是为Activity绑定对应的应用进程,AMS会判断目标进程是否存在,如果不存在的话,将会先用Zygote创建新的线程。

Zygote

        简单来说,AMS需要启动应用进程的时候,会通过Socket的方式与Zygote进程通信,让Zygote进程fork出所需要的应用进程。下面看一看Zygote怎么做到的。

public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
......
try {
......
String zygoteSocketName = "zygote";
......
Zygote.initNativeState(isPrimaryZygote);
zygoteServer = new ZygoteServer(isPrimaryZygote);
......
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
}

        这是ZygoteInit的main方法,这个进程在开机时便会启动,在这里启动了Zygote服务器,用于接受AMS发送的启动应用请求,进入ZygoteServer的runSelectLoop方法会发现 :

while(true){
......
ZygoteConnection connection=peers.get(pollIndex);
boolean multipleForksOK=!isUsapPoolEnabled()
&&ZygoteHooks.isIndefiniteThreadSuspensionSafe();
final Runnable command=connection.processCommand(this,multipleForksOK);
......
}

        截取了其中一小段关键代码,可以看出来server接受到请求之后将之交给了ZygoteConnection处理,再看一看怎么处理的:

......
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
return handleChildProc(parsedArgs, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
......
return null;
}

        这里就是熟悉的fork流程了,子进程的pid会是0,然后将该进程作为创建出的新进程再次进入ZygoteInit完成进程的初始化工作。具体来说是通过反射来创建需要的ActivityThread,然后运行其main方法。

protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
cl = Class.forName(className, true, classLoader);
Method m;
m = cl.getMethod("main", new Class[] { String[].class });
int modifiers = m.getModifiers();
return new MethodAndArgsCaller(m, argv);
}

        在ActivityThread的Main方法中, 它会通过binder机制调用AMS的attachApplication方法将自己信息注册在AMS中然后AMS会通过Binder机制通知ActivityThread进行后续步骤。

ActivityThread阶段

        ActivityThread收到通知之后,会通过Handler机制发送信息到ui线程,进入下一步方法。

performLaunchActivity

        这个方法是启动Activity的核心方法,主要完成了三件事创建目标Activity,为新Activity传入必要参数,初始化Activity并进入生命周期的onCreate流程。下面是这个方法的代码片段。

java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
appContext.getAttributionSource());
if (r.state != null) {
r.state.setClassLoader(cl);
}
appContext.setOuterContext(activity);
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.activityConfigCallback,
r.assistToken, r.shareableActivityToken);
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}

        可以看出来,创建Activity与启动Activity生命周期是通过Instrumentation实现的,就是通过intent启动Activity时利用到的类。它是Android应用与Android系统沟通的桥梁。

        先来看一下是怎么创建Activity实例的,下面是newActivity方法关键代码:

public Activity newActivity(ClassLoader cl, String className,
Intent intent) throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
//这个是获得的AppComponentFactory的方法
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass(className).newInstance();
}

         与创建ActivityThread的方法一样,也是通过反射的方式来创建新的Activity的。剩下两个方法比较直观,一个是绑定数据,以参数的形式传给Activity让它处理,一个是启动生命周期,则是执行Activity的performCreate方法,开始onCreate()进入生命周期的。

为什么这样做

        启动Activity的流程如此复杂,我觉得可以从进程与线程的角度来分析,首先呢,发起应用的进程不应当与被启动应用的进程有关系,因此需要由AMS所在的SystemServer进程负责启动,具体孵化新进程的任务交给了Zygote进程(补充一句,这俩系统进程信息传递用Socket是因为Binder机制需要多线程,但是fork机制不允许多线程)。当新的应用进程创建好之后,AMS再通知其启动目的Activity。

        从多线程的角度来看ActivityThread为什么要用Handler机制来开启Activity绘制流程,AMS通过binder机制通知ActivityThread时并不处于UI线程,因此通过Handler发送了EXECUTE_TRANSACTION信息到主线程,开启了Activity生命周期。

参考:

硬核!Android 应用启动全流程深度剖析!(建议收藏)

performCreate

       

感谢以上大佬,帮我在源码离迷路的时候找到方向。

最后

以上就是灵巧万宝路为你收集整理的Activity启动流程的全部内容,希望文章能够帮你解决Activity启动流程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部