Activity的创建过程分析

本文来自最近闲暇时查看android framework源码写的一篇文章,可能有错误之处,烦请各位大神指正。

整个Activity的启动创建过程是通过ActivityThread完成的,首先看一下ActivityThread中的main方法:

public static void main(String[] args) {  
        SamplingProfilerIntegration.start();  
        // CloseGuard defaults to true and can be quite spammy.  We  
        // disable it here, but selectively enable it later (via  
        // StrictMode) on debug builds, but using DropBox, not logs.  
        CloseGuard.setEnabled(false);  
        Environment.initForCurrentUser();    
        // Set the reporter for event logging in libcore  
        EventLogger.setReporter(new EventLoggingReporter());   
        Process.setArgV0("<pre-initialized>");  
        Looper.prepareMainLooper();   
        // 创建ActivityThread实例  
        ActivityThread thread = new ActivityThread();  
        thread.attach(false);  
        if (sMainThreadHandler == null) {  
            sMainThreadHandler = thread.getHandler();  
        }  
        AsyncTask.init();  
        if (false) {  
            Looper.myLooper().setMessageLogging(new  
                    LogPrinter(Log.DEBUG, "ActivityThread"));  
        }    
        Looper.loop();  
        throw new RuntimeException("Main thread loop unexpectedly exited");  
    }  
}  

 

     ActivityThread中的main()方法中对一个Looper对象进行初始化,形成一个消息循环,通过Looper.prepareMainLooper()和Loop.loop()实现

然后再调用thread.attach方法,

 

private void attach(boolean system) {

        sCurrentActivityThread = this;

        mSystemThread = system;

         .....

            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",

                                                    UserHandle.myUserId());

            RuntimeInit.setApplicationObject(mAppThread.asBinder());

            final IActivityManager mgr = ActivityManagerNative.getDefault();

            try {

               //与ActivitymanagerService进行通信

                mgr.attachApplication(mAppThread);

            } catch (RemoteException ex) {

                // Ignore

            }

            // Watch for getting close to heap limit.

            BinderInternal.addGcWatcher(new Runnable() {

                @Override public void run() {

                    if (!mSomeActivitiesChanged) {

                        return;

                    }

                    Runtime runtime = Runtime.getRuntime();

                    long dalvikMax = runtime.maxMemory();

                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();

                    if (dalvikUsed > ((3*dalvikMax)/4)) {

                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)

                                + " total=" + (runtime.totalMemory()/1024)

                                + " used=" + (dalvikUsed/1024));

                        mSomeActivitiesChanged = false;

                        try {

                            mgr.releaseSomeActivities(mAppThread);

                        } catch (RemoteException e) {

                        }

                    }

                }

            });

        }

……

    }

 

      通过ActivityManagerNative创建一个IActivityManager 以及ApplicationThread的实例mAppThread和ActivityManagerService进行交互,因为ActivityManagerService运行在一个独立的线程中,他是在zygote进程开启后创建的,该来用来跟zygote进程通信,从而创建对应的应用程序。ActivityManagerService跟应用程序交互就是通过ActivityManagerNative以及ApplicationThread实现的。ActivityManagerNative是继承自Binder的,首先ActivityThread获取AMSProxy,然后调用attachApplication函数将ActivityThread中创建的ApplicationThread传递给AMS,AMS会根据pid找到对应的ProcessRecord,然后将ApplicationThread保存在ProcessRecord.thread中

任何主线程的操作都会发送到这个Looper对应的Handler中去,它是ActivityThread中定义的一个内部类,名为H,继承自Handler。代码如下:

 private class H extends Handler {  
          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");  
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;  
                      r.packageInfo = getPackageInfoNoCheck(  
                            r.activityInfo.applicationInfo, r.compatInfo);  
                    handleLaunchActivity(r, null);  
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
                } break;  
                ...  
            }  
            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));  
        }  
         
        ...  
    }

 

    该handleLaunchActivity方法中执行了两个比较关键的步骤,一个是performLaunchActivity(),另一个是handleResumeActivity()。

 

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

    ...

     //创建Activity

       Activity activity = null;

        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();

        activity = mInstrumentation.newActivity(

                cl, component.getClassName(), r.intent);

        StrictMode.incrementExpectedActivityCount(activity.getClass());

        r.intent.setExtrasClassLoader(cl);

        if (r.state != null) {

            r.state.setClassLoader(cl);

        }

 

    try {

       //创建Application

        Application app=r.packageInfo.makeApplication(false,mInstrumentation);//创建Application,并将contextImp与Activity相关联

        if (activity != null) {  

         ...

      // 将contextImp与Window关联相关联            

       activity.attach(appContext, this, getInstrumentation(), r.token,

                    r.ident, app, r.intent, r.activityInfo, title, r.parent,

                    r.embeddedID, r.lastNonConfigurationInstances, config);

            ...

            activity.mCalled = false;

            mInstrumentation.callActivityOnCreate(activity, r.state);//调用Activity的OnCreate方法

            ...

        }

        ...

    }

    ...

}

 

在performLaunchActivity通过查找packageInfo以及反射机制的ClassLoader构建了一个activity,其中不得不提Instrumentation类,该类是一个辅助类,用于创建 Activity以及application,并通过Instrumentation对应的方法启动Activity的onCreate方法等生命周期方法。

再看一下activity.attach的方法,该方法用于构建一个PhoneWindow并赋值给mWindow 

final void attach(Context context, ActivityThread aThread,    
Instrumentation instr, IBinder token, int ident,    
Application application, Intent intent, ActivityInfo info,    
CharSequence title, Activity parentString id,    
Object lastNonConfigurationInstance,    
HashMap<String,Object> lastNonConfigurationChildInstances,    
Configuration config) {    
......      
mWindow = PolicyManager.makeNewWindow(this);    
setCallback(this);    
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {    
setSoftInputMode(info.softInputMode);    
}    
......    
setWindowManager(null, mToken, mComponent.flattenToString());    
......    
}  

 

     函数首先调用PolicyManager类的静态成员函数makeNewWindow来创建一个类型为PhoneWindow的应用程序窗口,并且保存在Activity类的成员变量mWindow中。有了这个类型为PhoneWindow的应用程序窗口,函数接下来还会调用它的成员函数setCallback、setSoftInputMode和setWindowManager来设置窗口回调接口、软键盘输入区域的显示模式和本地窗口管理器。

 

    构建完window对象后通过 mInstrumentation.callActivityOnCreate(activity, r.state)执行Activity的OnCreate方法,而onCreate方法执行了对应了setContentView操作,

 

 

public void setContentView(int layoutResID) { 

        getWindow().setContentView(layoutResID); 

    }

 

   即调用了通过Activity中attach方法中构建的phoneWindow的setContentView方法

 

public void setContentView(int layoutResID) { 

        if (mContentParent == null) { 

            installDecor(); 

        } else { 

            mContentParent.removeAllViews(); 

        } 

        mLayoutInflater.inflate(layoutResID, mContentParent); 

        final Callback cb = getCallback(); 

        if (cb != null) { 

            cb.onContentChanged(); 

        } 

    } 

 

    mLayoutInflater.inflate(layoutResID, mContentParent)用来构建用户自定义的布局,关于inflate的具体加载过程可以查看http://www.atatech.org/articles/37004

installDecor方法用于构造一个DecorView对象DecorView是整个View的根布局,他继承自Framelayout。

 

private void installDecor() { 

        if (mDecor == null) { 

            mDecor = generateDecor(); 

            ...... 

        } 

        if (mContentParent == null) { 

            mContentParent = generateLayout(mDecor); 

          //设置标题

            mTitleView = (TextView)findViewById(com.android.internal.R.id.title); 

            if (mTitleView != null) { 

                if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) { 

                    View titleContainer = findViewById(com.android.internal.R.id.title_container); 

                    if (titleContainer != null) { 

                        titleContainer.setVisibility(View.GONE); 

                    } else { 

                        mTitleView.setVisibility(View.GONE); 

                    } 

                    if (mContentParent instanceof FrameLayout) { 

                        ((FrameLayout)mContentParent).setForeground(null); 

                    } 

                } else { 

                    mTitleView.setText(mTitle); 

                } 

            } 

        } 

    } 

 

    PhoneWindow类的成员函数installDecor就会调用另外一个成员函数generateDecor来创建一个DecorView对象,并且保存在PhoneWindow类的成员变量mDecor中。  PhoneWindow类的成员函数installDecor还会检查前面加载的窗口布局文件是否包含有一个id值为“title”的TextView控件。如果包含有的话,就会将它保存在PhoneWindow类的成员变量mTitleView中,用来描述当前应用程序窗口的标题栏。但是,如果当前应用程序窗口是没有标题栏的,即它的Feature位FEATURE_NO_TITLE的值等于1,那么PhoneWindow类的成员函数installDecor就需要将前面得到的标题栏隐藏起来

     这里的构建过程也就是对应了文章http://www.atatech.org/articles/37843第一个图中的Activity 、PhoneWindow以及DecorView。

    这里只完成了整个Activity 、Phonewindow以及DecorView,以及自定义布局的初始化操作并没有完整显示View,即通过setContentView()方法并没有显示出任何东西来,而仅仅是将Phonewindow->mDecor->mContentParent->(customer layout)一个这样的树状结构给搭建好了而已。而View的展示是在handleResumeActivity完成的。

 

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,

        boolean reallyResume) {

    ...

//通过 mInstrumentation.callActivityOnResume执行Activity自己的Resume方法

    ActivityClientRecord r = performResumeActivity(token, clearHide);    if (r != null) {

        final Activity a = r.activity;

        ...

        if (r.window == null && !a.mFinished && willBeVisible) {

            r.window = r.activity.getWindow();//获取前面设置的window

            View decor = r.window.getDecorView();//获取前面设置的DecorView

            decor.setVisibility(View.INVISIBLE);

            ViewManager wm = a.getWindowManager();

            WindowManager.LayoutParams l = r.window.getAttributes();

            a.mDecor = decor;

            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;

            l.softInputMode |= forwardBit;

            if (a.mVisibleFromClient) {

                a.mWindowAdded = true;

                wm.addView(decor, l);

            }

            ...

        }

    ...

    }

}

 

handleResumeActivity ()方法是通过Instrumentation调用Activity的onResume()方法。

    下面的wm.addView()方法非常关键,wm是上面a.getWindowManager()获取到的,a是Activity,getWindowManager()就是返回它的mWindowManger对象,而这个对象是WindowManagerImpl,它的内部方法大部分是代理的WindowManagerGlobal.

   然而,这个WindowManger的addView()是干了什么呢?

 

public void addView(View view, ViewGroup.LayoutParams params,

        Display display, Window parentWindow) {

    ...

    ViewRootImpl root;

    View panelParentView = null;

    ...

        root = new ViewRootImpl(view.getContext(), display);

        view.setLayoutParams(wparams);

        mViews.add(view);

        mRoots.add(root);

        mParams.add(wparams);

    }

    // do this last because it fires off messages to start doing things

    try {

        root.setView(view, wparams, panelParentView);

    } catch (RuntimeException e) {

        ...

        throw e;

    }

}

 

    从上面的代码可以看出,addView方法中,new了一个ViewRootImpl对象,然后调用ViewRootImpl.setView()方法。

 

android.view.ViewRootImpl.setView()

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {

    synchronized (this) {

        if (mView == null) {

            mView = view;

            ...

            // Schedule the first layout -before- adding to the window

            // manager, to make sure we do the relayout before receiving

            // any other events from the system.

            requestLayout();

            ...

            view.assignParent(this);

            ...

        }

    }

}

     并执行requestLayout(),接着就可以执行http://www.atatech.org/articles/37843中提到的measure,layout,draw三步操作了

    最后通过r.activity.makeVisible()方法将整个Acitivty设置为可见状态

   本文源码均来自开源社区:https://github.com/android/platform_frameworks_base

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值