Android Activity从创建到显示流程

Posted 瞌睡先生想睡觉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Activity从创建到显示流程相关的知识,希望对你有一定的参考价值。

看我的代码请注意写了注释的地方,这些往往是关键地方

最近准备看android的View工作流程,但是根据网上的博客所说,必然就会涉及到Window,DecorView,WindowManager,ViewRootImpl这些相关的东西,所以在网络上众多大神博客的指导下去阅读了Android的部分源码,
发现Android的很多东西还都是一环套一环的,有些东西单单只是看部分代码就会云里雾里,一脸懵逼.结合我原来看Handler机制源码的经验就先从Activity的启动开始看起,诸位请随我看下去

Activty是在ActivtyThread的中创建的,简单说下ActivtyThread,这个类就是我们app的入口,然后有着我们在学习Java的时候常见的main方法,里面有一个Looper循环,保持主线程不死.Activity的创建在ActivtyThread内部H类中,H类继承自Handler,里面处理了众多Android系统的事件,其中就包括Activity的启动创建

	//此处只贴部分代码,完整代码请自行查看Android源码
    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;
	//操作启动Activity
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) 
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) 
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        if (!ThreadedRenderer.sRendererDisabled) 
            GraphicsEnvironment.earlyInitEGL();
        
        WindowManagerGlobal.initialize();

        Activity a = performLaunchActivity(r, customIntent);//执行启动Activity,在里面会去创建Activity,并且会执行Activity的onCreate和onStart生命周期

        if (a != null) 
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);//准备执行Activty的Resume生命周期

            if (!r.activity.mFinished && r.startsNotResumed) 
                // The activity manager actually wants this one to start out paused, because it
                // needs to be visible but isn't in the foreground. We accomplish this by going
                // through the normal startup (because activities expect to go through onResume()
                // the first time they run, before their window is displayed), and then pausing it.
                // However, in this case we do -not- need to do the full pause cycle (of freezing
                // and such) because the activity manager assumes it can just retain the current
                // state it has.
                performPauseActivityIfNeeded(r, reason);

                // We need to keep around the original state, in case we need to be created again.
                // But we only do this for pre-Honeycomb apps, which always save their state when
                // pausing, so we can not have them save their state when restarting from a paused
                // state. For HC and later, we want to (and can) let the state be saved as the
                // normal part of stopping the activity.
                if (r.isPreHoneycomb()) 
                    r.state = oldState;
                
            
         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();
            
        
    


    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) 
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) 
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        

        ComponentName component = r.intent.getComponent();
        if (component == null) 
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        

        if (r.activityInfo.targetActivity != null) 
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        

        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try 
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);//反射创建Activity
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) 
                r.state.setClassLoader(cl);
            
         catch (Exception e) 
            if (!mInstrumentation.onException(activity, e)) 
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            
        

        try 
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) 
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) 
                    config.updateFrom(r.overrideConfig);
                
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) 
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                
                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.configCallback);//设置Activity所必要的相关数据,在这里面会去初始化Window和WindowManager

                if (customIntent != null) 
                    activity.mIntent = customIntent;
                
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) 
                    activity.setTheme(theme);
                

                activity.mCalled = false;
                if (r.isPersistable()) 
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                 else 
                    mInstrumentation.callActivityOnCreate(activity, r.state);//执行Activty的onCreate
                
                if (!activity.mCalled) 
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) 
                    activity.performStart();//执行Activity的onStart
                    r.stopped = false;
                
                if (!r.activity.mFinished) 
                    if (r.isPersistable()) 
                        if (r.state != null || r.persistentState != null) 
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        
                     else if (r.state != null) 
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    
                
                if (!r.activity.mFinished) 
                    activity.mCalled = false;
                    if (r.isPersistable()) 
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                     else 
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    
                    if (!activity.mCalled) 
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    
                
            
            r.paused = true;

            mActivities.put(r.token, r);

         catch (SuperNotCalledException e) 
            throw e;

         catch (Exception e) 
            if (!mInstrumentation.onException(activity, e)) 
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            
        

        return activity;
    

在这里我们只去看一些关闭部分的代码,不会去整个的完全解析,所以,如果想完全搞懂这部分代码,请去阅读专门的博客

在上面我们简单看了一下Activity的创建和生命周期的执行流程,下面就来看下Activity的attach方法


    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) 
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window, activityConfigCallback);//实例化PhoneWindow对象,Window是一个抽象类,具体功能由其子类PhoneWindow实现
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) 
            mWindow.setSoftInputMode(info.softInputMode);
        
        if (info.uiOptions != 0) 
            mWindow.setUiOptions(info.uiOptions);
        
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) 
            if (lastNonConfigurationInstances != null) 
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
             else 
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            
        

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);//创建WindowManager对象
        if (mParent != null) 
            mWindow.setContainer(mParent.getWindow());
        
        mWindowManager = mWindow.getWindowManager();//拿到WindowManager对象
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);
    

代码运行到attach,根据我们在上面看到Activity的生命周期执行流程就可以知道,下一步就要执行Activity的onCreate的方法了,DecorView就是在Activity的create生命周期中创建的.
通常具体而言就是我们调用setContentView方法时创建的.


	//这个就是我们调用的setContentView方法
    public void setContentView(@LayoutRes int layoutResID) 
        getWindow().setContentView(layoutResID);//实际上调用的PhoneWindow的setContentView方法
        initWindowDecorActionBar();
    	
		
    public Window getWindow() 
        return mWindow;//返回的就是刚刚在attach中创建的PhoneWindow
    
		

下面来看下PhoneWindow的setContentView的方法


    //这个方法有重载的方法,我们只需要看其中一个就可以了
    @Override
    public void setContentView(int layoutResID) 
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) //mContentParent是DecorView中的布局,在初始化DecorView的同时也会初始化mContentParent
            installDecor();//初始化DecorView
         else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) 
            mContentParent.removeAllViews();
        

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) 
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
         else 
            mLayoutInflater.inflate(layoutResID, mContentParent);//将要设置的布局添加到mContentParent中
        
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) 
            cb.onContentChanged();
        
        mContentParentExplicitlySet = true;
    
		

	//初始化DecorView
	private void installDecor() 
        mForceDecorInstall = false;
        if (mDecor == null以上是关于Android Activity从创建到显示流程的主要内容,如果未能解决你的问题,请参考以下文章

Android 插件化Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 一 | Activity 进程相关源码 )

Android Activity启动流程源码解析

Android Activity启动流程源码解析

Activity具体是怎么创建的?又是怎么显示出来的?

Android 图形系统详解

Android8.0(API26)之Activity启动流程(显示启动)