Activity启动流程以及View的绘制流程

来源:互联网 发布:java socket 发送 编辑:程序博客网 时间:2024/06/07 10:22

前言

当我们启动一个Activity之后,Activity上面的视图就会展现在我们面前,我们知道,视图就是所谓的View,既然是View,那么肯定有一个绘制的过程,那么Activity的启动过程和这个视图的绘制是如何联系起来的呢?今天就大概给大家介绍一下。

先给出一张图,总结一下Activity启动流程

这里写图片描述

启动Activity会调用startActivity,最终调用下面的方法

//Activity中的方法 public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {        if (mParent == null) {        //调用Instrumentation的execStartActivity            Instrumentation.ActivityResult ar =                mInstrumentation.execStartActivity(                    this, mMainThread.getApplicationThread(), mToken, this,                    intent, requestCode, options);          ......
//Instrumentation中的方法 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);                    if (am.match(who, null, intent)) {                        am.mHits++;                        if (am.isBlocking()) {                            return requestCode >= 0 ? am.getResult() : null;                        }                        break;                    }                }            }        }        try {            intent.migrateExtraStreamToClipData();            intent.prepareToLeaveProcess();            int result =             //真正启动Activity逻辑在这            ActivityManagerNative.getDefault()                .startActivity(whoThread, who.getBasePackageName(), intent,                        .......

我们看看getDefault方法

//ActivityManagerNative的方法static public IActivityManager getDefault() {        return gDefault.get();    }

接着看gDefault.get()返回什么

  private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {        protected IActivityManager create() {            IBinder b = ServiceManager.getService("activity");            if (false) {                Log.v("ActivityManager", "default service binder = " + b);            }            IActivityManager am = asInterface(b);            if (false) {                Log.v("ActivityManager", "default service = " + am);            }            return am;        }    };}

我们看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);    }

最终返回的是ActivityManagerProxy这个对象。ActivityManagerProxy是ActivityManagerNative的一个内部类,实现了IActivityManager接口,我们看它的startActivity方法

class ActivityManagerProxy implements IActivityManager{    public ActivityManagerProxy(IBinder remote)    {        mRemote = remote;    }    public IBinder asBinder()    {        return mRemote;    }    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,            String resolvedType, IBinder resultTo, String resultWho, int requestCode,            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {        Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IActivityManager.descriptor);        data.writeStrongBinder(caller != null ? caller.asBinder() : null);        data.writeString(callingPackage);        intent.writeToParcel(data, 0);        data.writeString(resolvedType);        data.writeStrongBinder(resultTo);        data.writeString(resultWho);        data.writeInt(requestCode);        data.writeInt(startFlags);        if (profilerInfo != null) {            data.writeInt(1);            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);        } else {            data.writeInt(0);        }        if (options != null) {            data.writeInt(1);            options.writeToParcel(data, 0);        } else {            data.writeInt(0);        }        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);        reply.readException();        int result = reply.readInt();        reply.recycle();        data.recycle();        return result;    }

这里就是通过Binder方式向AMS通信,请求启动一个新的进程,那么当AMS接收到请求以后,是如何反馈回来的呢?我们去看AMS的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 options) {        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,            resultWho, requestCode, startFlags, profilerInfo, options,            UserHandle.getCallingUserId());    }
 @Override    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {        enforceNotIsolatedCaller("startActivity");        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,                false, ALLOW_FULL_ONLY, "startActivity", null);        // TODO: Switch to user app stacks here.        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,                profilerInfo, null, null, options, false, userId, null, null);    }

从这里调用了ActivityStackSupervisor的startActivityMayWait方法,后面的步骤比较多,我用一张图来展示一下,具体代码就不贴出来了,有兴趣的话大家去看源码

这里写图片描述

最后会调用
ActivityStackSupervisor的realStartActivityLocked方法,

 final boolean realStartActivityLocked(ActivityRecord r,            ProcessRecord app, boolean andResume, boolean checkConfig)            throws RemoteException {.....  app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),                    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);                    .....

这里调用了app.thread的scheduleLaunchActivity方法,那么这个app.thread是什么呢?是IApplicationThread,它的实现类是

class ApplicationThreadProxy implements IApplicationThread 

ApplicationThreadProxy的scheduleLaunchActivity通过Binder方式通知ApplicationThread

 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) throws RemoteException {        Parcel data = Parcel.obtain();        data.writeInterfaceToken(IApplicationThread.descriptor);        intent.writeToParcel(data, 0);        data.writeStrongBinder(token);        data.writeInt(ident);        info.writeToParcel(data, 0);        curConfig.writeToParcel(data, 0);        if (overrideConfig != null) {            data.writeInt(1);            overrideConfig.writeToParcel(data, 0);        } else {            data.writeInt(0);        }        compatInfo.writeToParcel(data, 0);        data.writeString(referrer);        data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);        data.writeInt(procState);        data.writeBundle(state);        data.writePersistableBundle(persistentState);        data.writeTypedList(pendingResults);        data.writeTypedList(pendingNewIntents);        data.writeInt(notResumed ? 1 : 0);        data.writeInt(isForward ? 1 : 0);        if (profilerInfo != null) {            data.writeInt(1);            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);        } else {            data.writeInt(0);        }        mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,                IBinder.FLAG_ONEWAY);        data.recycle();    }

ApplicationThread是ActivityThread的一个内部类,

  private class ApplicationThread extends ApplicationThreadNative {
  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) {                ....                  sendMessage(H.LAUNCH_ACTIVITY, r);

在ApplicationThread的scheduleLaunchActivity方法中发送了一个消息,H是在ActivityThread中创建的一个Handler对象,会根据当前传过来的消息做不同的操作。我们去看看H的handleMessage方法对这个消息是如何处理的。

 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);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                } break;

调用了handleLaunchActivity方法,里面又调用了performLaunchActivity,我们看这个方法

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {  .....        Activity activity = null;        try {            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();            //创建Activity对象            activity = mInstrumentation.newActivity(                    cl, component.getClassName(), r.intent);            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 =             //创建Application对象            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) {                Context appContext = createBaseContextForActivity(r, activity);                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());                Configuration config = new Configuration(mCompatConfiguration);                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "                        + r.activityInfo.name + " with config " + config);                        + //调用activity的attach方法                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);                if (customIntent != null) {                    activity.mIntent = customIntent;                }                r.lastNonConfigurationInstances = null;                activity.mStartedActivity = false;                int theme = r.activityInfo.getThemeResource();                if (theme != 0) {                    activity.setTheme(theme);                }                activity.mCalled = false;                if (r.isPersistable()) {//调用activity的onCreate方法                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);                } else {                    mInstrumentation.callActivityOnCreate(activity, r.state);                }                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的start方法                    activity.performStart();                    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;    }

上面有个比较重要的方法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) {        attachBaseContext(context);        mFragments.attachHost(null /*parent*/);        //创建PhoneWindwo对象        mWindow = new PhoneWindow(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());            }        }    //给PhoneWindow设置WindowManger        mWindow.setWindowManager(                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),                mToken, mComponent.flattenToString(),                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);        if (mParent != null) {            mWindow.setContainer(mParent.getWindow());        }        //获取PhoneWindow的WindowManger        mWindowManager = mWindow.getWindowManager();        mCurrentConfig = config;    }

在执行performLaunchActivity的过程中,会调用Activity的onCreate方法,我们通常在此方法中会使用setContentView来加载页面布局,在这个过程中会创建DecorView,并将我们的布局添加到DecorView下面的一个id为content的FrameLayout中

然后就是ActivityThread的handleResumeActivity方法

 final void handleResumeActivity(IBinder token,            boolean clearHide, boolean isForward, boolean reallyResume) {    ....    //调用activity的resume方法        ActivityClientRecord r = performResumeActivity(token, clearHide);.....            if (r.window == null && !a.mFinished && willBeVisible) {            //获取activity的window对象,也就是phonewindow,在activity的attach方法中已经创建完毕                r.window = r.activity.getWindow();                //获取decorview,在setContentview方法中已经创建                View decor = r.window.getDecorView();                decor.setVisibility(View.INVISIBLE);                //获取activity的windowmanager                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;                    //将decorview添加到activity的window中,此处的wm实际是windowmanagerglobal对象                    wm.addView(decor, l);                }           ......

我们去看看WindowManagerGlobal的addView方法

  public void addView(View view, ViewGroup.LayoutParams params,            Display display, Window parentWindow) {        if (view == null) {            throw new IllegalArgumentException("view must not be null");        }        if (display == null) {            throw new IllegalArgumentException("display must not be null");        }        if (!(params instanceof WindowManager.LayoutParams)) {            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");        }      ......        ViewRootImpl root;        View panelParentView = null;        synchronized (mLock) {          .....            //创建ViewRootImpl对象            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) {            // BadTokenException or InvalidDisplayException, clean up.            synchronized (mLock) {                final int index = findViewLocked(view, false);                if (index >= 0) {                    removeViewLocked(index, true);                }            }            throw e;        }       .....

这里的重点就是创建了ViewRootImpl对象,在ViewRootImpl中有一个重要的方法,

 void checkThread() {        if (mThread != Thread.currentThread()) {            throw new CalledFromWrongThreadException(                    "Only the original thread that created a view hierarchy can touch its views.");        }    }

这个方法的作用是检查当前更新view的线程是否是主线程,如果不是,会报出异常

接下来我们看看ViewRootImpl的setView方法

 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {    ......      // 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();                .....}

ViewRootImpl的setView方法中调用了requestLayout,这就是View的绘制起点。

 @Override    public void requestLayout() {        if (!mHandlingLayoutInLayoutRequest) {            checkThread();            mLayoutRequested = true;            scheduleTraversals();        }    }

最终会调用到performTraversals方法,

 private void performTraversals() { .....  int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);                    int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);   // 执行DecorView的onMeasure测量                    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);                    ....                    //执行DecorView的onLayout                                performLayout(lp, desiredWindowWidth, desiredWindowHeight);......                    //执行DecorView的onDraw绘制                     performDraw();

至此,我们从Activity的流程就分析到了View是如何开始绘制的。

最后给大家一份链接,介绍的也是Activity的启动流程
Android应用启动分析

0 1