Android Activity启动流程分析

白诗秀儿 关注

收藏于 : 2018-05-31 23:13   被转藏 : 1   

概述

Activity作为Android的四大组件之一,Android主要的界面组成部分,用于直接跟用户进行交互操作,在面试中与Activity相关的知识也是经常被问到,如果你面试的高级岗位,那么对Activity的启动和绘制流程就必须的熟悉,本文将从Activity的启动流程来分析Activity。启动Activity的方式大致有两种:一种是在桌面点击应用程序的图标,进入应用程序的主界面;另一种是在应用程序中,进入一个新的Activity。前者属于launcher启动的范畴,本文不做具体的深入分析,后面会具体的分析,不过它的实质是从一个应用的Activity进入另一个应用Activity。
因此,不管是从桌面进入应用主界面,还是在应用里进入一个新的Activity,最终都会调用Activity$startActivity方法。
值得注意的是,Android 5.0,7.0等版本中启动Activity的流程略微有一些细小的改变,但这并不妨碍我们理解Activity的启动流程。

Binder机制

首先,我们要介绍下Android系统中一个重要的内容:Binder机制。为了满足进程间的通信,Android系统将进程分为了用户(Zygote)进程和系统(SystemServer)进程以及各种应用进程等,为了能够实现各种进程之间的通讯,Android系统采用了自己的进程间通讯方式Binder机制。其中主要涉及到了四种角色:Binder Client,Binder Server,Binder Manager, Binder driver。各种角色之间的关系可以参考下面这张图的介绍:

关于Binder机制的具体内容,可以参考Android Binder跨进程通信原理一文。

启动Activity流程解读

当我们使用startActivity() 启动另一个Activity后,主要会调用以下的一些函数。

MyActivity.startActivity() 
Activity.startActivity() 
Activity.startActivityForResult 
Instrumentation.execStartActivty 
ActivityManagerNative.getDefault().startActivityAsUser() 

首先,我们来看一下startActivity()函数的源码:

@Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            startActivityForResult(intent, -1);
        }
    }

其实,startActivity还有几个其他重载的方法,但是最终都会执行到Activity$startActivityForResult方法。如果是调用startActivity(intent)启动Activity,那么requestCode参数则传入-1,表示需要返回Activity的数据。

到此继续往下看,startActivityForResult方法的具体实现如下:

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

在上面的代码中,mParent进行了一个判Null操作,可以发现由于我们是第一次启动Activity,所以这里的mParent为空,所以会执行if分之,然后调用mInstrumentation.execStartActivity方法,并且这里需要注意的是,有一个判断逻辑。即:

if (requestCode >= 0) {
    mStartedActivity = true;
}

前面说过,调用startActivityForResult的时候只有requestCode的值大于等于0,onActivityResult才会被回调。

Instrumentation

然后我们看一下mInstrumentation.execStartActivity方法的具体实现。在看execStartActivity方法之前,首先看一下Instrumentation,Instrumentation是android系统中启动Activity的一个实际操作类,也就是说Activity在应用进程端的启动实际上就是Instrumentation执行的。那为什么是这样呢?实际上acitivty的启动分为应用进程端的启动和SystemServer服务进程端的启动的,多个应用进程相互配合最终完成了Activity在系统中的启动的,而在应用进程端的启动实际的操作类就是Intrumentation来执行的。

为了方便理解,我们直接看execStartActivity函数源码:

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        result = am.onStartActivity(intent);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

如上,execStartActivity主要有以下几个参数:
this,为启动Activity的对象;
contextThread,为Binder对象,是主进程的context对象;
token,也是一个Binder对象,指向了服务端一个ActivityRecord对象;
target,为启动的Activity;
intent,启动的Intent对象;
requestCode,请求码;
options,参数;
通过,execStartActivity方法可以发现,该方法主要调用ActivityManager.getService()方法,继续查看ActivityManager$getService源码。

/**  
 * @hide  
 */  
public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    } 

//继续查看  

private static final Singleton<IActivityManager> IActivityManagerSingleton =  
        new Singleton<IActivityManager>() {  
            @Override  
            protected IActivityManager create() {  
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);  
                final IActivityManager am = IActivityManager.Stub.asInterface(b);  
                return am;  
            }  
        };  

 //...code  

}

可以发现,IActivityManager.Stub.asInterface(b),那么继续看asInterface方法的实现:

static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

asInterface()返回一个ActivityManagerProxy对象,ActivityManagerProxy继承与IActivityManager,到了这里就引出了我们android系统中很重要的一个概念:Binder机制。

IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE)

如上,是获取一个关联了系统服务ActivityManagerService的Binder对象。所以,IBinder最终和ActivityManagerService形成了绑定关系。

public class ActivityManagerService extends IActivityManager.Stub  
       implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  


   }  

所以,ActivityManager.getService().startActivity(…)的最终调用的是ActivityManagerService的startActivity方法。

ActivityManagerService启动Activity

首先来看一下,ActivityManagerService$startActivity的相关源码。

@Override  
public final int startActivity(IApplicationThread caller, String callingPackage,  
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,  
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {  
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,  
            resultWho, requestCode, startFlags, profilerInfo, bOptions,  
            UserHandle.getCallingUserId());  
}  

ActivityManagerService启动Activity主要会涉及到以下的一些方法。

ActivityManagerService.startActivity() 
ActvityiManagerService.startActivityAsUser() 
ActivityStackSupervisor.startActivityMayWait() 
ActivityStackSupervisor.startActivityLocked() 
ActivityStackSupervisor.startActivityUncheckedLocked() 
ActivityStackSupervisor.startActivityLocked() 
ActivityStackSupervisor.resumeTopActivitiesLocked() 
ActivityStackSupervisor.resumeTopActivityInnerLocked() 

当ActivityManagerService调用startActivity方法后,该方法调用的是startActivityAsUser(),该方法的源码如下:

@Override  
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,  
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,  
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {  
    enforceNotIsolatedCaller("startActivity");  
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),  
            userId, false, ALLOW_FULL_ONLY, "startActivity", null);  
    // TODO: Switch to user app stacks here.  
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,  
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,  
            profilerInfo, null, null, bOptions, false, userId, null, null,  
            "startActivityAsUser");  
}  

可以看到这里只是进行了一些关于userid的逻辑判断,然后就调用mStackSupervisor.startActivityMayWait方法,该方法涉及的源码比较多,下面截取一些核心的代码实现:

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
            ...

            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);
            ...
            return res;
    }

该方法在启动Activity后执行了一些逻辑判断后,最终调用startActivityLocked方法。

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage,
            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            ActivityContainer container, TaskRecord inTask) {
        int err = ActivityManager.START_SUCCESS;

        ...
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

        ...
        return err;
    }

这个方法中主要构造了ActivityManagerService端的Activity对象–>ActivityRecord,并在执行了一些逻辑判断后调用了startActivityUncheckedLocked方法。

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {
        ...
        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
        targetStack.mLastPausedActivity = null;
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        if (!launchTaskBehind) {
            // Don't set focus on an activity that's going to the back.
            mService.setFocusedActivityLocked(r, "startedActivity");
        }
        return ActivityManager.START_SUCCESS;
    }

startActivityUncheckedLocked方法中只要执行了不同启动模式不同栈的处理,并最后调用了startActivityLocked的重载方法。

final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        ...
        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

而这个startActivityLocked方法主要执行初始化了windowManager服务,然后调用resumeTopActivitiesLocked方法。

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = mFocusedStack;
        }
        // Do targetStack first.
        boolean result = false;
        if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (stack == targetStack) {
                    // Already started above.
                    continue;
                }
                if (isFrontStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }

该函数最终又调用了resumeTopActivityLocked方法,

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }

ApplicationThread

前面说过,ApplicationThread是ActivityThread的内部类,因此ApplicationThread可以调用外部类ActivityThread的方法,启动Activity的操作交给了ActivityThread来处理。那么首先来看一下ApplicationThread$scheduleLaunchActivity的源码实现。

@Override  
       public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
               ActivityInfo info, Configuration curConfig, Configuration overrideConfig,  
               CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,  
               int procState, Bundle state, PersistableBundle persistentState,  
               List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,  
               boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {  

           updateProcessState(procState, false);  

           ActivityClientRecord r = new ActivityClientRecord();  

           r.token = token;  
           r.ident = ident;  
           r.intent = intent;  
           r.referrer = referrer;  
           r.voiceInteractor = voiceInteractor;  
           r.activityInfo = info;  
           r.compatInfo = compatInfo;  
           r.state = state;  
           r.persistentState = persistentState;  

           r.pendingResults = pendingResults;  
           r.pendingIntents = pendingNewIntents;  

           r.startsNotResumed = notResumed;  
           r.isForward = isForward;  

           r.profilerInfo = profilerInfo;  

           r.overrideConfig = overrideConfig;  
           updatePendingConfiguration(curConfig);  

           sendMessage(H.LAUNCH_ACTIVITY, r);  
       }  

上面代码最终调用了ActivityThread$sendMessage函数,该部分代码如下:

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {  
        if (DEBUG_MESSAGES) Slog.v(  
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)  
            + ": " + arg1 + " / " + obj);  
        Message msg = Message.obtain();  
        msg.what = what;  
        msg.obj = obj;  
        msg.arg1 = arg1;  
        msg.arg2 = arg2;  
        if (async) {  
            msg.setAsynchronous(true);  
        }  
        mH.sendMessage(msg);  
} 

上面使用了Handler机制,来看一下H$handleMessage源码。

private class H extends Handler {  

    //...code  
    public void handleMessage(Message msg) {  
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));  
            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);  
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");  
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
                } break;  

    //...code  

}  

当接受到消息后,最终调用ActivityThread$handleLaunchActivity方法启动Activity。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {  
    //...  

    Activity a = performLaunchActivity(r, customIntent);  

    //...  

    if (a != null) {  
        //...  

        handleResumeActivity(r.token, false, r.isForward,  
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);  

        //...  

    } else {  
        // If there was an error, for any reason, tell the activity manager to stop us.  
        try {  
             ActivityManager.getService()  
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,  
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);  
            } catch (RemoteException ex) {  
                throw ex.rethrowFromSystemServer();  
            }  
    }  

}  

也就是performLaunchActivity,到此我相信大部分的同学都可以看得懂了

 阅读文章全部内容  
点击查看
文章点评
相关文章
白诗秀儿 关注

文章收藏:1308

TA的最新收藏