Activity的创建,和生命周期的调用

前言

从第一天接触Android开发开始,大家都知道Activity是Android中最最最重要的一个组件。既然很重要,很多在Android开发岗位工作几年了,都对Activity讲不出个所以然出来。比如:
1.Activity的创建
2.Activity生命周期函数的调用
既然这么重要,这么多问题困扰小伙伴们,希望通过本章的学习,帮助小伙伴们对Activity有个全新的认识。

众所周知,java程序想要开启需要依赖于main方法,也就是程序入口(主线程)进入。熟悉的小伙伴可能都知道在Android当中存在一个叫做ActivityThread的类,这个类代表的是Android当中的主线程,而在这个类当中会有一个比较熟悉的main方法,Android在打开app时首先调用的是ActivityThread的main方法,这也就是一个app进程的启动点。

##ActivityThread
public static void main(String[] args) {
        ...
        Looper.prepareMainLooper();
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();  //1
        thread.attach(false, startSeq); //2
        ...
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
}

在main方法的注释1处,创建了ActivityThread,接着在注释2处,调用了attach方法,意为连接,具体连接什么,我们接着往下分析。

##ActivityThread
private void attach(boolean system, long startSeq) {
        ...
        if (!system) {
            ...
            final IActivityManager mgr = ActivityManager.getService();  //1
            try {
                mgr.attachApplication(mAppThread, startSeq);  //2
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ...
        } else {
            ...
        }
        ...
}

attach方法,在注释1处,通过AIDL,得到AMS的本地代理对象IActivityManager ,作用应用进程请求系统进程的接口,实现跟AMS服务跨进程间通信。这里设计到AIDL的用法,和AMS相关的基础知识,这部分内容不在本章节探讨。接着看注释2,使用IActivityManager 对象调用了attachApplication方法,主要是为了连接Application。Application这个类小伙伴们肯定是不陌生的,一般会在这个类中去初始化一些需要在Activity启动之前初始化的资源,或是配置一些整个应用需要用到的东西,让真个App(任何类中)都能访问到。那么这里跟AMS进行连接,主要让当前App跟Android系统绑定起来,方便系统管理当前App。

##ActivityManagerService
public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            //获取pid
            int callingPid = Binder.getCallingPid();  //1
            //获取uid
            final int callingUid = Binder.getCallingUid();  //2
            final long origId = Binder.clearCallingIdentity();
            //连接Application
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);  //3
            Binder.restoreCallingIdentity(origId);
        }
}

attachApplication是AMS中的一个方法,注释1和2分别获取到pid和uid(由系统创建,并分配,并且是处以没有进程使用)。这里小伙伴们可以猜想一下,获取到pid和uid肯定是把它分配到当前进程。在注释3,可以看到pid和uid传入到了attachApplicationLocked这个方法中。

##ActivityManagerService
private final boolean attachApplicationLocked(IApplicationThread thread,
                                                  int pid, int callingUid, long startSeq) {
        ProcessRecord app;  //1
        long startTime = SystemClock.uptimeMillis();
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);  //2
            }
        } 
        ...
        if (app.instr != null) {  //当前进程是否正在活动
           thread.bindApplication(processName, appInfo, providers, app.instr.mClass,
                    profilerInfo, app.instr.mArguments, app.instr.mWatcher, app.instr.mUiAutomationConnection,
                    testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()),
                    app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, isAutofillCompatEnabled);   //3
        } else {
            //Application 绑定到当前线程
            thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                    null, null, null, testMode, mBinderTransactionTrackingEnabled,
                    enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, isAutofillCompatEnabled);  //4
        }
        ...
        //检测最可见的Activity是否在运行进程中等待,如果再则创建Activity
        if (mStackSupervisor.attachApplicationLocked(app)) {  //5
            didSomething = true;
        }
        ...
}

attachApplicationLocked方法中,注释1处的ProcessRecord是个进程记录类,小伙伴们可以把这个类理解成为一个javabean,用来保存当前进程先关的一些信息(如pid、uip、ApplicationInfo等),在注释2中,根据pid获取到了这个类。注释3和注释4都是为了绑定Application,调用的是IApplicationThread 中的bindApplication方法,而IApplicationThread 它是一个AIDL接口,作用是系统进程请求应用进程的接口。而它的实现类是在ActivityThread中的一个内部类ApplicationTread继承了IApplicationThread.Stub。注释5是开始创建Activity。这里我们分开来探讨绑定Application和创建Activity。

绑定Application
##ActivityThread.ApplicationThread
public final void bindApplication(String processName...boolean autofillCompatibilityEnabled) {
        ...
        setCoreSettings(coreSettings);
        AppBindData data = new AppBindData();
        data.processName = processName;  //当前进程名字
        data.appInfo = appInfo;     //app信息
        data.providers = providers; //providers
        ...
        //最后使用Handler发送消息,并携带AppBindData数据
        sendMessage(H.BIND_APPLICATION, data);
}

在ActivityThread.ApplicationTread类中,bindApplication方法携带了一系列参数,把这些数据封装成了一个AppBindData 对象,最后使用Handler发送消息,并携带AppBindData数据。H是ActivityThread中的内部类,是Handler的子类。

##ActivityThread.H
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;
            ...
        }
        ...
}

handleMessage方法是H中的方法,主要是用来处理消息。

##ActivityThread 
private void handleBindApplication(AppBindData data) {
        ...
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);  //1
        ...
        Application app;
        ...
        //创建Application
        app = data.info.makeApplication(data.restrictedBackupMode, null);  //2
        ...
        //调用Application中的onCreate方法
        mInstrumentation.callApplicationOnCreate(app);  //3
        ...
}

##Instrumentation
public void callApplicationOnCreate(Application app) {
        app.onCreate();
}

handleBindApplication方法中,注释1,获取Application的上下文,也就是getApplicationContext()获取到的ContextImpl ,ContextImpl 是Context的子类。注释2,通过类加载器,和反射创建出Application。注释3,接着可以看到Application的onCreate方法的调用。

小结,链接Application,可以理解为三个步骤,第一个步骤获取pid和uid,第二步通过IApplicationThread请求当前应用进程,第三步创建Application。

创建Activity
##ActivityStackSupervisor
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        ...
        if (realStartActivityLocked(activity, app,
                top == activity /* andResume */, true /* checkConfig */)) {
            didSomething = true;
        }
        ...
}

经过一系列的检测或判断后,会realStartActivityLocked方法,真正的开始Activity的解锁(创建)。

##ActivityStackSupervisor
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                                          boolean andResume, boolean checkConfig) throws RemoteException {
        ...
        // 创建启动Activity
        final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                r.appToken);
        clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                System.identityHashCode(r), r.info,
                mergedConfiguration.getGlobalConfiguration(),
                mergedConfiguration.getOverrideConfiguration(), r.compat,
                r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                profilerInfo));  //添加LaunchActivityItem的回调
        // Set desired final state.
        final ActivityLifecycleItem lifecycleItem;
        if (andResume) {
            lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
        } else {
            lifecycleItem = PauseActivityItem.obtain();
        }
        clientTransaction.setLifecycleStateRequest(lifecycleItem);
        // 通过生命周期管理对象ClientLifecycleManager,来管理Activity的生命周期状态
        mService.getLifecycleManager().scheduleTransaction(clientTransaction);
        ...
        return true;
}

此处,添加LaunchActivityItem。再后续的真正开始创建Activity时会用到。

##ClientLifecycleManager
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        //ClientTransaction是个javabean 实现了Parcelable 序列化。
        //schedule()方法内部,会回调到ActivityThread.ApplicationThread的scheduleTransaction()方法
        transaction.schedule();
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }
}

接着会走到

##ActivityThread.ApplicationTread
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        //ActivityThread.this 指的是父类ClientTransactionHandler
        ActivityThread.this.scheduleTransaction(transaction);
}

##ClientTransactionHandler
void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        //发送Handler消息
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

在handleMessage方法中处理的EXECUTE_TRANSACTION这条消息。

##ActivityThread.H
public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            ...
            case EXECUTE_TRANSACTION:
                final ClientTransaction transaction = (ClientTransaction) msg.obj;
                //开始执行
                mTransactionExecutor.execute(transaction);
                if (isSystem()) {
                    // Client transactions inside system process are recycled on the client side
                    // instead of ClientLifecycleManager to avoid being cleared before this
                    // message is handled.
                    transaction.recycle();
                }
                // TODO(lifecycler): Recycle locally scheduled transactions.
                break;
                ...
        }
        ...
}

接着看execute方法。

##TransactionExecutor
public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
        executeCallbacks(transaction);  //1
        executeLifecycleState(transaction);  //5
        mPendingActions.clear();
        log("End resolving transaction");
}

##TransactionExecutor
public void executeCallbacks(ClientTransaction transaction) {
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();  //2
        ...
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);  //3
            ...
            item.execute(mTransactionHandler, token, mPendingActions);  //4
            ...
        }
}

executeCallbacks方法,注释1执行回调。注释2获取到ClientTransaction中的ClientTransactionItem集合。注释3处理回调,这里获取到的ClientTransactionItem是LaunchActivityItem。注释4调用LaunchActivityItem中的execute方法。注释5是执行生命周期状态的改变,这里没有给小伙伴们贴出代码,感兴趣的小伙伴去看看。举个例子,比如Activity首次创建,默认的生命周期状态是ON_CREATE,再进行完onCreate方法调用结束后,生命周期状态值会往后移,也就是状态改变成ON_START,onStart方法调用结束,状态改变成ON_RESUME。

##LaunchActivityItem
public void execute(ClientTransactionHandler client, IBinder token,
                        PendingTransactionActions pendingActions) {
        ...
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);  //1
        ...
}

execute方法中,ClientTransactionHandler是个抽象类,他的子类是ActivityThread。接着调用到的是
ActivityThread中的handleLaunchActivity方法。

##ActivityThread
public Activity handleLaunchActivity(ActivityClientRecord r,
                                         PendingTransactionActions pendingActions, Intent customIntent) {
        ...
        //开始执行
        final Activity a = performLaunchActivity(r, customIntent);   //1
        ...
        return a;
}

注释1,开始执行启动Activity的创建。

##ActivityThread
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;   //1
        ...
        ContextImpl appContext = createBaseContextForActivity(r);   //2
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();   //3
            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);  //4
           ...
        } catch (Exception e) {
           ...
        }
        ...
        //调用Activity的OnCreate()方法
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);   //5
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);   
        }
        ...
        return activity;
}

performLaunchActivity方法中,注释1获取Activity信息。 注释2获取Activity 上下文。注释3获取到ClassLoader 类加载器对象。注释4使用ClassLoader(类加载器)加载出Activity,再使用反射new出Activity。注释5调用Activity的onCreate方法。

##Instrumentation
public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
       
        activity.performCreate(icicle);  //1
        postPerformCreate(activity);
}

注释1处,调用Activity中performCreate方法

##Activity
final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
}

##Activity
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        mCanEnterPictureInPicture = true;
        restoreHasCurrentPermissionRequest(icicle);
        //onCreate 生命周期方法被调用
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        ...
}

performCreate方法中会调用onCreate方法。到这里Activity的创建已经结束啦。

备注:文中Android源码版本9.0

作者:Alan
原创博客,请注明转载处....

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

推荐阅读更多精彩内容