第九章四大组件的工作过程(一)Activity的工作过程(Android开发艺术探索)

来源:互联网 发布:淘宝产品图片怎么做 编辑:程序博客网 时间:2024/05/22 04:42

阅读本章将了解:

四大组件:Activity、Service、BroadCastReceiver、ContentProvider的工作过程,而不是使用

9.1 四大组件的运行状态

除了BroadCastReceiver,其他都必须在Manifest中注册

BroadCastReceiver既可以在Manifest中注册,也可以通过代码注册;

在调用方式上,Activity、Service、BroadCastReceiver都需要借助Intent,ContentProvider不用借助Intent

Activity :

展示型组件,展示界面、用户交互

Service :

计算型组件,主线程运行,有启动状态(无需外界交互)和绑定状态(方便外界交互)

BroadCastReceiver :

消息型组件,不适合执行耗时操作,
静态注册(不启动应用就可以接收消息)和动态注册(启动应用才可以接收消息)
ContentProvider:数据共享型组件,不需要手动停止,内部需要实现增删改查操作,是在Binder线程池中调用,所以要处理好方法线程同步。

下面进入正题:
9.2 Activitiy的工作过程

本节主要分析activity的启动流程,而不是陷入代码细节无法自拔,避免出现“只见树木,不见树林”,也不涉及启动模式和任务栈,主要是内部启动过程。

我们从Activity的startActivity方法开始分析,startActivity有好几种重载方式,但是最终都会调用startActivityForResult

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {    if (mParent == null) {        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) {            mStartedActivity = true;        }        cancelInputsAndStartExitTransition(options);        // 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 == null的逻辑即可,我们看mMainThread.getApplicationThread()参数,ApplicationThread是ActivityThread的内部类,在activity的启动过程发挥着重要作用

下面我们看execStartActivity方法:

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();//真正实现启动activity方法        int result = ActivityManagerNative.getDefault()            .startActivity(whoThread, who.getBasePackageName(), intent,                    intent.resolveTypeIfNeeded(who.getContentResolver()),                    token, target != null ? target.mEmbeddedID : null,                    requestCode, 0, null, options);//启动之后检查Activity的启动结果(是否成功,如果Manifest没注册,那么就会返回失败)        checkStartActivityResult(result, intent);    } catch (RemoteException e) {        throw new RuntimeException("Failure from system", e);    }    return null;}

其中:ActivityManagerNative.getDefault()是通过单例获取的,代码如下:

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 getDefault() {    return gDefault.get();}

另外我们再看看启动之后有个checkStartActivityResult方法,作用是检查Activity的结果

/** @hide */public static void checkStartActivityResult(int res, Object intent) {    if (res >= ActivityManager.START_SUCCESS) {        return;    }    //检查各种情况    switch (res) {        case ActivityManager.START_INTENT_NOT_RESOLVED:        case ActivityManager.START_CLASS_NOT_FOUND:            if (intent instanceof Intent && ((Intent)intent).getComponent() != null)                throw new ActivityNotFoundException(                        "Unable to find explicit activity class "                        + ((Intent)intent).getComponent().toShortString()                        + "; have you declared this activity in your AndroidManifest.xml?");            throw new ActivityNotFoundException(                    "No Activity found to handle " + intent);        case ActivityManager.START_PERMISSION_DENIED:            throw new SecurityException("Not allowed to start activity "                    + intent);        case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:            throw new AndroidRuntimeException(                    "FORWARD_RESULT_FLAG used while also requesting a result");        case ActivityManager.START_NOT_ACTIVITY:            throw new IllegalArgumentException(                    "PendingIntent is not an activity");        case ActivityManager.START_NOT_VOICE_COMPATIBLE:            throw new SecurityException(                    "Starting under voice control not allowed for: " + intent);        case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:            // Fail silently for this case so we don't break current apps.            // TODO(b/22929608): Instead of failing silently or throwing an exception,            // we should properly position the activity in the stack (i.e. behind all current            // user activity/task) and not change the positioning of stacks.            Log.e(TAG,                    "Not allowed to start background user activity that shouldn't be displayed"                    + " for all users. Failing silently...");            break;        default:            throw new AndroidRuntimeException("Unknown error code "                    + res + " when starting " + intent);    }}

最后我们来看看类结构关系 :

public abstract class ActivityManagerNative extends Binder implements IActivityManager

另外它的子类才是具体实现:

public final class ActivityManagerService extends ActivityManagerNative {@Overridepublic 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());}@Overridepublic 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);    // 切换到用户应用程序堆栈    return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,            profilerInfo, null, null, options, false, userId, null, null);}}

可以看到,启动方法又转移到了mStackSupervisor.startActivityMayWait方法中去了,
接着步骤如下:

startActivityMayWait中调用了startActivityLocked方法;startActivityLocked中调用了startActivityUncheckedLocked方法;startActivityUncheckedLocked中调用了ActivityStack的resumeTopActivitysLocked方法

直接看重点:

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {    if (mStackSupervisor.inResumeTopActivity) {        // Don't even start recursing.        return false;    }    boolean result = false;    try {        // Protect against recursion.        mStackSupervisor.inResumeTopActivity = true;        if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {            mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;            mService.updateSleepIfNeededLocked();        }//看这里        result = resumeTopActivityInnerLocked(prev, options);    } finally {        mStackSupervisor.inResumeTopActivity = false;    }    return result;}

看代码可以知道,resumeTopActivityLocked又调用了resumeTopActivityInnerLocked
resumeTopActivityInnerLocked又调用了ActivityStackSupervisor的startSpecificActivityLocked方法

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, true);    r.task.stack.setLaunchTime(r);    if (app != null && app.thread != null) {        try {            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0                    || !"android".equals(r.info.packageName)) {                // Don't add this if it is a platform component that is marked                // to run in multiple processes, because this is actually                // part of the framework so doesn't make sense to track as a                // separate apk in the process.                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,                        mService.mProcessStats);            }//看这里            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, true);}

看代码可以知道,startSpecificActivityLocked又调用了realStartActivityLocked
我们继续来看realStartActivityLocked方法,其中最重要的代码是:

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的类型是IApplicationThread ,IApplicationThread 的声明如下:

public interface IApplicationThread extends IInterface {    void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,            int configChanges, boolean dontReport) throws RemoteException;    void scheduleStopActivity(IBinder token, boolean showWindow,            int configChanges) throws RemoteException;    void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;    void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;    void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)            throws RemoteException;    void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;    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;    void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,            List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed,            Configuration config, Configuration overrideConfig) throws RemoteException;    void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException;    void scheduleDestroyActivity(IBinder token, boolean finished,            int configChanges) throws RemoteException;    void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,            int resultCode, String data, Bundle extras, boolean sync,            int sendingUser, int processState) throws RemoteException;    static final int BACKUP_MODE_INCREMENTAL = 0;    static final int BACKUP_MODE_FULL = 1;    static final int BACKUP_MODE_RESTORE = 2;    static final int BACKUP_MODE_RESTORE_FULL = 3;    void scheduleCreateBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo,            int backupMode) throws RemoteException;    void scheduleDestroyBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo)            throws RemoteException;    void scheduleCreateService(IBinder token, ServiceInfo info,            CompatibilityInfo compatInfo, int processState) throws RemoteException;    void scheduleBindService(IBinder token,            Intent intent, boolean rebind, int processState) throws RemoteException;    void scheduleUnbindService(IBinder token,            Intent intent) throws RemoteException;    void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,            int flags, Intent args) throws RemoteException;    void scheduleStopService(IBinder token) throws RemoteException;

因为它 extends IInterface,所以它是Binder类型的接口,包含了大量activity的启动停止和service的启动停止服务的方法。

那么IApplicationThread 的实现类是哪个类呢?
答案就是ActivityThread的内部类:ApplicationThread
类关系如下:

private class ApplicationThread extends ApplicationThreadNative {public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {

绕了一大圈,Activity的启动过程最终回到了ApplicationThread中,ApplicationThread通过scheduleLaunchActivity来启动Activity

代码如下:

@Overridepublic 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) {    updateProcessState(procState, false);    ActivityClientRecord r = new ActivityClientRecord();    r.token = token;    r.ident = ident;    r.intent = intent;    r.referrer = referrer;    r.voiceInteractor = voiceInteractor;    r.activityInfo = info;    r.compatInfo = compatInfo;    r.state = state;    r.persistentState = persistentState;    r.pendingResults = pendingResults;    r.pendingIntents = pendingNewIntents;    r.startsNotResumed = notResumed;    r.isForward = isForward;    r.profilerInfo = profilerInfo;    r.overrideConfig = overrideConfig;    updatePendingConfiguration(curConfig);//发送消息    sendMessage(H.LAUNCH_ACTIVITY, r);}

在ApplicationThread中,scheduleLaunchActivity实现很简单,就是发送一个启动Activity的消息交由Handle处理,Handle处理如下:

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方法

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {    Activity a = performLaunchActivity(r, customIntent);    if (a != null) {        r.createdConfig = new Configuration(mConfiguration);        Bundle oldState = r.state;        handleResumeActivity(r.token, false, r.isForward,                !r.activity.mFinished && !r.startsNotResumed);

从代码可以看出,performLaunchActivity方法最终完成了Activity的创建和启动,并且通过handleResumeActivity来调用被Activity启动的onResume方法

看performLaunchActivity方法的实现可以知道它完成了如下几件事:

1、从ActivityRecord中获取待启动的Activity的组件信息

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

2、通过Instrumentation的newActivity方法使用类加载器创建Activity对象

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

3、通过LoadedApk的makeApplication方法来尝试创建Application对象

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

我们继续看makeApplication方法的实现:

public Application makeApplication(boolean forceDefaultAppClass,        Instrumentation instrumentation) {    if (mApplication != null) {        return mApplication;    }    Application app = null;    String appClass = mApplicationInfo.className;    if (forceDefaultAppClass || (appClass == null)) {        appClass = "android.app.Application";    }    try {        java.lang.ClassLoader cl = getClassLoader();        if (!mPackageName.equals("android")) {            initializeJavaContextClassLoader();        }        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);        app = mActivityThread.mInstrumentation.newApplication(                cl, appClass, appContext);        appContext.setOuterContext(app);    } catch (Exception e) {        if (!mActivityThread.mInstrumentation.onException(app, e)) {            throw new RuntimeException(                "Unable to instantiate application " + appClass                + ": " + e.toString(), e);        }    }    mActivityThread.mAllApplications.add(app);    mApplication = app;    if (instrumentation != null) {        try {            instrumentation.callApplicationOnCreate(app);        } catch (Exception e) {            if (!instrumentation.onException(app, e)) {                throw new RuntimeException(                    "Unable to create application " + app.getClass().getName()                    + ": " + e.toString(), e);            }        }    }    // Rewrite the R 'constants' for all library apks.    SparseArray<String> packageIdentifiers = getAssets(mActivityThread)            .getAssignedPackageIdentifiers();    final int N = packageIdentifiers.size();    for (int i = 0; i < N; i++) {        final int id = packageIdentifiers.keyAt(i);        if (id == 0x01 || id == 0x7f) {            continue;        }        rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);    }    return app;}

从makeApplication的实现可以看出,如果Application创建过了就不再创建了,也就意味着一个应用就一个Application对象,Application的创建和Activity的创建过程一样,都是通过类加载器创建的,创建完毕后,系统会通过instrumentation.callApplicationOnCreate(app);方法来调用Application的onCreate方法。

4、创建创建ContextImpl对象并通过Activity的Attach方法来完成重要数据的初始化

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,            r.referrer, r.voiceInteractor);

ContextImpl是Context的具体实现,ContextImpl是通过Activity的Attach方法和Activity建立关联的;另外,attach方法中,activity还会完成window的创建并建立自己和window的关联,这样当window接收外部事件就可以把事件传递给Activity了。

5、调用Activity的onCreate方法

mInstrumentation.callActivityOnCreate(activity, r.state);

onCreate方法被调用,那么Activity的启动也就完成了。

为了更清楚的说明activity的启动过程,来看图:
这里写图片描述

0 0