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

       

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值