Android Activity启动过程简读 <1>

来源:互联网 发布:nico sm是什么软件 编辑:程序博客网 时间:2024/06/16 08:05

平时工作中经常会谈一些Activity启动过程,周期之类的话题.其实整体单纯来说还是比较简单.

<1> : Activity的启动都是从startActivity(...)开始.

<2> : 对比Activity的周期中涉及到几个阶段,如果onCreate,onResume...,当发现程序调用这些方法时,第一时间想到的是framework的Activity管理根据状态在回调这些方法.

<3> : 谈及第二点,比较Activity和Fragement在生命周期中,会发现Fragement包含一个attach方法,而Activity似乎没有,用过Fragment的attach方法的都知道它的好,Activity实际也是有的,隐藏着,当然实际上个人觉得提供给开发者用处不大.但是这个在framework里面却非常的重要的.

<4> : 涉及的代码(主要的部分):framework/base/core/java/android/app下的Activity,ActivityThread,Instrumentation,然后就是framework/base/services/java/com/android/server/am目录下,重点是ActivityStack和ActivityManagerService.分别编译生成framework.jar和services.jar.

<5> : 创建内容,前面谈到蓝牙服务的时候,顺便说了很多其他服务也是在SystemServer中创建的,所以ActivityManagerService也是在系统Server中创建的.com.android.server.SystemServer中的init2的线程run中.framework很多地方调用这个服务的方式:

(ActivityManagerService)ActivityManagerNative.getDefault().***

<6> : 当启动一个app时,相应创建一个ActivityThread进行管理所有的Activity,而这些Activity的运行状态是靠对应的ActivityRecord记录的,如果是APP第一个Activity,那么会同时创建一个process进程,进程默认名是APP的包名,当然APP也可以在主配置xml中自行安排Activity进程,同一个进程的Activity,进程只会创建一次,但是ActivityThread数量应该是和Activity一一对应的.注意前面<3> 的回调在管理处是先处理对应的Application的周期回调Activity,不知这句话是否说准了.

<7> : 回调生命周期各方法是通过Handle消息机制完成的.在ActivityThread中处理的.

<8> : ActivityThread和ActivityManagerService频繁的互相调用对方,是非常繁琐的,但是线索还是比较清晰的.


好了,开始从Activity类的startActivity方法开始:

@Override    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);        }    }

跟着下去,关键的几句:

mInstrumentation.execStartActivity(                    this, mMainThread.getApplicationThread(), mToken, this,                    intent, requestCode, options);

然后到Instruction类中:

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


根据上面的几条中说明的,下面调用ActivityManagerService类.

int result = ActivityManagerNative.getDefault()                .startActivity(whoThread, intent,                        intent.resolveTypeIfNeeded(who.getContentResolver()),                        token, target != null ? target.mWho : null,                        requestCode, 0, null, null, options);

进入ActivityManagerService类中:

public final int startActivity(IApplicationThread caller,            Intent intent, String resolvedType, IBinder resultTo,            String resultWho, int requestCode, int startFlags,            String profileFile, ParcelFileDescriptor profileFd, Bundle options) {        return startActivityAsUser(caller, intent, resolvedType, resultTo, resultWho, requestCode,                startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());    }    public final int startActivityAsUser(IApplicationThread caller,            Intent intent, String resolvedType, IBinder resultTo,            String resultWho, int requestCode, int startFlags,            String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {        enforceNotIsolatedCaller("startActivity");        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,                false, true, "startActivity", null);        return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,                resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,                null, null, options, userId);    }


其中mMainStack是ActivityStack类对应的startActivityMayWait方法中:

int res = startActivityLocked(caller, intent, resolvedType,                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,                    startFlags, options, componentSpecified, null);


然后继续:

private final void startActivityLocked(ActivityRecord r, boolean newTask,            boolean doResume, boolean keepCurTransition, Bundle options) {        final int NH = mHistory.size();


在这个方法中打出log,会发现NH>1始终成立,这个NH是获得mHistory Activity是否在后台和后台数量,因为桌面Launcher总是会启动,所以NH第一个一般是Launcher,doResume也是为true.mHostory是ArrayList保存的所有ActivityRecord,这个也是没创建一个Activity对应创建一个,做好Activity状态等记录.

if (doResume) {            resumeTopActivityLocked(null);        }

看到这个方法最后面:

startSpecificActivityLocked(next, true, true);

看到这个地方就越来越明显了,

private final void startSpecificActivityLocked(ActivityRecord r,            boolean andResume, boolean checkConfig) {        // Is this activity's application already running?        ProcessRecord app = mService.getProcessRecordLocked(r.processName,                r.info.applicationInfo.uid);                if (r.launchTime == 0) {            r.launchTime = SystemClock.uptimeMillis();            if (mInitialStartTime == 0) {                mInitialStartTime = r.launchTime;            }        } else if (mInitialStartTime == 0) {            mInitialStartTime = SystemClock.uptimeMillis();        }                if (app != null && app.thread != null) {            try {                app.addPackage(r.info.packageName);                realStartActivityLocked(r, app, andResume, checkConfig);                return;            } catch (RemoteException e) {                Slog.w(TAG, "Exception when starting activity "                        + r.intent.getComponent().flattenToShortString(), e);            }            // If a dead object exception was thrown -- fall through to            // restart the application.        }        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,                "activity", r.intent.getComponent(), false, false);    }


看到最后startProcessLocked方法.这个在ActivityManagerService类中,直接看里面的重点:

// Start the process.  It will either succeed and return a result containing            // the PID of the new process, or else throw a RuntimeException.            Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",                    app.processName, uid, uid, gids, debugFlags, mountExternal,                    app.info.targetSdkVersion, null, null);

这个非常重要,可以说是新的Activity的启动,上面程序创建ActivityThread进程,从而且确定创建一个新的Activity,那么就可以查看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 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 thread = new ActivityThread();        thread.attach(false);

同样在ActivityThread类中看他的attach方法:

RuntimeInit.setApplicationObject(mAppThread.asBinder());            IActivityManager mgr = ActivityManagerNative.getDefault();            try {                mgr.attachApplication(mAppThread);            } catch (RemoteException ex) {                // Ignore            }

调用了ActivityManagerService中的attachApplication方法.

public final void attachApplication(IApplicationThread thread) {        synchronized (this) {            int callingPid = Binder.getCallingPid();            final long origId = Binder.clearCallingIdentity();            attachApplicationLocked(thread, callingPid);            Binder.restoreCallingIdentity(origId);        }    }


继续跟踪attachApplicationLocked方法,这个里面要仔细看,不然还真容易走眼:

mMainStack.realStartActivityLocked(hr, app, true, true)

看来又回到ActivityStack中:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,                    System.identityHashCode(r), r.info,                    new Configuration(mService.mConfiguration),                    r.compat, r.icicle, results, newIntents, !andResume,                    mService.isNextTransitionForward(), profileFile, profileFd,                    profileAutoStop);

又到ActivityThread中:直接看下面的

queueOrSendMessage(H.LAUNCH_ACTIVITY, r);

终于到了发送Handle message了

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);

然后:

Activity a = performLaunchActivity(r, customIntent);


然后继续:

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);        }        Activity activity = null;        try {            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);            }        } 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) {                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(appContext, this, getInstrumentation(), r.token,                        r.ident, app, r.intent, r.activityInfo, title, r.parent,                        r.embeddedID, r.lastNonConfigurationInstances, config);

终于看到activity的第一个生命周期attach方法了.

上面一路还有很多判断条件,可以自行根据自己想了解的部分,参考上面的思路跟踪,应该没什么问题,打log.




后面的继续... ...















0 0
原创粉丝点击