App是如何启动?Activity生命周期是如何调用的?

学java的都知道main函数是程序的入口,那么Android是不是也有一个类似main函数的入口呢?

答案是肯定的,在Android的源码中ActivityThread.java中,也有一个main函数public static void main(String[] args),那么就从这里开始找APP是如何启动的。

在main函数里可以看到这样的一段代码

public static void main(String[] args){
    //准备开启一个主线程的Looper,这个mainlooper是由当前Android环境所创建的
    Looper.prepareMainLooper();

    //实例化当前ActivityThread对象,并调用了attach()方法
    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    ...省略...

    //开始循环获取消息队列
    Looper.loop();
}

接着看thread.attach做了什么事

 private void attach(boolean system) {

   ...省略...

        //注意:这里很重要
        //通过ActivityManager的getService()方法来获取activity管理接口对象,
        //那么getService()方法又做了什么呢,
        //拿到mgr后有调了attachApplication()又做了什么呢,下面会做详细的介绍
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
 }

接着我们看看IActivityManager是怎么获取到的

/**
 *跟着方法的调用可以看到这里很明显的用了单例模式,所以我们直接找单例实例化对象的地方
 */
public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
            @Override
            protected IActivityManager create() {

                //这里通过ServiceManager获取activity服务的引用
                //并通过Binder跨进程通信机制来实例化IActivityManager对象
                //可能到这里你会问为啥要通过Binder来获取IActivityManager,
                //Binder机制在Android系统架构中大量使用,其中Activity间通信就可以使用Binder机制
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

接下来看看 mgr.attachApplication(mAppThread);做了什么事
其中mAppThread在ActivityThread中作为成员变量实例化了,当然mAppThread也是通过Binder机制来获取的

 final ApplicationThread mAppThread = new ApplicationThread();

private class ApplicationThread extends IApplicationThread.Stub {}


在attachApplication()方法中只是将ApplicationThread通过Parcel打包起来,也就是说将ApplicationThread与ActivityThread关联起来。

public void attachApplication(IApplicationThread app) throws RemoteException {
            Parcel _data = Parcel.obtain();
            Parcel _reply = Parcel.obtain();

            try {
                _data.writeInterfaceToken("android.app.IActivityManager");
                _data.writeStrongBinder(app != null ? app.asBinder() : null);
                this.mRemote.transact(11, _data, _reply, 0);
                _reply.readException();
            } finally {
                _reply.recycle();
                _data.recycle();
            }

}

到这里我们并没有发现接下来到底是怎样执行的,在ApplicationThread中你会发现大量类似跟Activity生命周期相关的方法,那么这些是不是就是调用Activity生命周期的方法呢?

我们接着以生命周期onCreate()方法为例讲解

在这些方法里面最后都发送了Activity状态的消息,不妨猜测一下Activity生命周期的调用是通过handle消息机制来实现的

scheduleLaunchActivity
scheduleResumeActivity
scheduleDestroyActivity

    @Override
    public final void scheduleLaunchActivity(...省略...) {

       ...省略...

        //发送LAUNCH_ACTIVITY消息
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }

接下来找H的这个handler实现,每种状态都调用了以handle***开头的方法。

private class H extends Handler {
    public static final int LAUNCH_ACTIVITY         = 100;
    public static final int PAUSE_ACTIVITY          = 101;
    public static final int PAUSE_ACTIVITY_FINISHING= 102;

   ...省略...

    public void handleMessage(Message msg) {

        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                r.packageInfo = getPackageInfoNoCheck(
                        r.activityInfo.applicationInfo, r.compatInfo);

                //调用Launch相关的方法
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
            case RELAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                ActivityClientRecord r = (ActivityClientRecord)msg.obj;

                //调用Relaunch相关的方法
                handleRelaunchActivity(r);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;

            ...省略...
        }
    }
}

紧接着在handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");里面会发现调用了Activity a = performLaunchActivity(r, customIntent);方法,继续跟着源码,在performLaunchActivity()方法里你可以发现最终通过Instrumentation来回调生命周期的方法

 if (r.isPersistable()) {

      // instrumentation是Android系统里面的一套控制方法或者“钩子”。
      //这些钩子可以在正常的生命周期(正常是由操作系统控制的)之外控制Android控件的运行,
      //其实指的就是Instrumentation类提供的各种流程控制方法
      mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
  } else {
      mInstrumentation.callActivityOnCreate(activity, r.state);
  }


//Instrumentation类
 public void callActivityOnCreate(Activity activity, Bundle icicle,
        PersistableBundle persistentState) {
    prePerformCreate(activity);

    //这里控制onCreate回调
    activity.performCreate(icicle, persistentState);
    postPerformCreate(activity);
}

//最终在Activity.java里面回调了onCreate()
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    mCanEnterPictureInPicture = true;
    restoreHasCurrentPermissionRequest(icicle);
    if (persistentState != null) {

        //onCreate生命周期
        onCreate(icicle, persistentState);
    } else {
        onCreate(icicle);
    }
    ...省略...
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容