Activity启动流程笔记(一)

来源:互联网 发布:centos防火墙关闭端口 编辑:程序博客网 时间:2024/05/21 00:15

从startActivity开始说起:

public void startActivity(Intent intent, Bundle options) {        if (options != null) {            startActivityForResult(intent, -1, options);        } else {            // Note we want to go through this call for compatibility with            // applications that may have overridden the method.            startActivityForResult(intent, -1);        }    }

进入startActivityForResult看看:

/**     * Launch an activity for which you would like a result when it finished.     * When this activity exits, your     * onActivityResult() method will be called with the given requestCode.      * Using a negative requestCode is the same as calling      * {@link #startActivity} (the activity is not launched as a sub-activity).     *     * <p>Note that this method should only be used with Intent protocols     * that are defined to return a result.  In other protocols (such as     * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may     * not get the result when you expect.  For example, if the activity you     * are launching uses the singleTask launch mode, it will not run in your     * task and thus you will immediately receive a cancel result.     *     * <p>As a special case, if you call startActivityForResult() with a requestCode      * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your     * activity, then your window will not be displayed until a result is      * returned back from the started activity.  This is to avoid visible      * flickering when redirecting to another activity.      *     * <p>This method throws {@link android.content.ActivityNotFoundException}     * if there was no Activity found to run the given Intent.     *     * @param intent The intent to start.     * @param requestCode If >= 0, this code will be returned in     *                    onActivityResult() when the activity exits.     * @param options Additional options for how the Activity should be started.     * See {@link android.content.Context#startActivity(Intent, Bundle)     * Context.startActivity(Intent, Bundle)} for more details.     *     * @throws android.content.ActivityNotFoundException     *     * @see #startActivity      */    public void startActivityForResult(Intent intent, int requestCode, Bundle options) {        if (mParent == null) {/*1*/            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;            }            final View decor = mWindow != null ? mWindow.peekDecorView() : null;            if (decor != null) {                decor.cancelPendingInputEvents();            }            // 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 表示Activity的父Activity,在用ActivityGroup的时候会出现这种情况,现在几乎不会用到,所以直接看mParent != null这种情况。在进入mInstrumentation的execStartActivity方法之前先看看参数:mMainThread.getApplicationThread()返回一个AplicationThread对象,这个对象其实是一个Binder,用于AMS与Activity通信。mMainThread是ActivityThread,ActivityThread是一个app的入口,mToken是一个AppWindowToken类型的对象,专门标识Activity类型的Window。

来看下Instrumentation的execStartActivity:

public ActivityResult execStartActivity(            Context who, IBinder contextThread, IBinder token, Activity target,            Intent intent, int requestCode, Bundle options) {        IApplicationThread whoThread = (IApplicationThread) contextThread;        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 = ActivityManagerNative.getDefault()                .startActivity(whoThread, who.getBasePackageName(), intent,                        intent.resolveTypeIfNeeded(who.getContentResolver()),                        token, target != null ? target.mEmbeddedID : null,                        requestCode, 0, null, null, options);            checkStartActivityResult(result, intent);        } catch (RemoteException e) {        }        return null;    }

主要看这段代码:ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
这个方法参数有点多,先看ActivityManagerNative.getDefault这个函数,他其实返回了一个AMS在客户端的代理,即一个ActivityManagerProxy

static public IActivityManager getDefault() {        return 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;        }    };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);    }

可以得知之前的startActivity调用的是ActivityManagerProxy中的方法
看到ActivityManagerProxy与ActivityManagerService都继承自ActivityManagerNative,可以想到AIDL,启动Activity需要通过AIDL跨进程与AMS交互,所以在ActivityManagerProxy的startActivity会将AIDL需要的参数进行快进程传递

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,            String resolvedType, IBinder resultTo, String resultWho, int requestCode,            int startFlags, String profileFile,            ParcelFileDescriptor profileFd, 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);        data.writeString(profileFile);        if (profileFd != null) {            data.writeInt(1);            profileFd.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;    }

可以看到IApplicaiotnThread对象也被包装成一个binder传递到AMS端,传递的实际是个ApplicationThreadProxy类型,用于AMS向ActivityThread通信,控制Activity。
至此,就进入到AMS中进行后续的启动。

0 0
原创粉丝点击