四大组件的工作过程探索(一)

四大组件的运行状态:

Android中的四大组件中除了BroadcastReceiver以外,其他三种组件都必须在Android Mainfrst中注册。对于,BroadcastReceiver来说,他既可以在AndroidMainfrst中注册也可以通过代码来注册。在调用方式上,Activity,Service和BroadcastReceiver需要借助Intent,而ContentProvider则无需借助Intent。

Activity的工作过程:

为了方便日常的开发工作,系统对四大组件的工作过程进行了很大程度的封装,这使得开发者无需关注实现细节即可快速的使用四大组件。Activity作为很重要的一个组件,其内部工作过程系统当然也是做了很多的封装,这种封装使得启动一个Activity变得异常的简单。在显示调用的情形下,只需要通过如下代码即可完成:

Intent intent=new Intent(this,TestActivity.class);
startActivity(intent);

通过上面的代码即可启动一个具体的activity,然后新Activity就会被系统启动并展示在 用户的眼前,这个过程对于Android开发者来说最普通不过了,这也是很理所当然的事情,但是有没有想过系统内部到底是如何启动一个Activity的呢?下面我们就来介绍一下。

注意一点:在研究内部实现上应该更加侧重于对整体流程的把握,而不能深入代码细节不能自拔,太深入代码细节往往会导致越看越迷茫的撞到。无法对整体流程建立足够的认识,取而代之的是繁琐的细节。但是代码的细节本身不具有太多的指导意义,因此这种学习状态是要极力避免的。所以本博客会侧重于对Activity工作过程的分析整体流程。

我们从Acitivity的startActivity的方法开始分析,startActivity的方法有好几种重载方式,但是他们最终都会调用startActivityForResult方法,实现如下:

public void startActivityForResult(Intent intent, int requestCode, 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) {
                // 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;
            }
        } 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这部分逻辑,mParent代表的是ActivityGroup,ActivityGroup最开始被用来在一个界面中嵌入多个子Activity,但是其在API13中已经被废弃了,系统推荐采用Fragment来代替ActivityGroup,Fragment的好处就不多说了、在上面的代码中需要注意mMainThread.getApplicationThread()这个参数,他的类型是ApplicationThread,ApplicationThread是ActivityThread在Activity的启动过程中发挥着很重要的作用。接着看一下Instrumentation的execStartActiivty方法。如下所示:

 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= 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;
    }
从上面的代码来看,启动Actiivty真正的实现由ActivityManagerNative.getDefault()的startActivity方法完成。ActivityManagerService(简称AMS)继承自Binder并实现了IActivityManager这个Binder接口,因此AMS也是一个Binder,他是IActivityManager的具体实现。由于ActivityManagerNative.getDefault()其实是一个IActivityManager类型的Binder对象,因此他的具体实现是AMS。可以发现,在ActivityManagerNative中。AMS这个Binder对象采用单例模式对外提供,Singleton是一个单利的封装类,第一次调用它的get方法时他会通过create方法来初始化AMS这个Binder对象,在后续的调用中则直接返回之前创建的对象,源码如下:

static public IActivityManager More ...getDefault() {
return gDefault.get();
}

private static final Singleton gDefault = new Singleton() {
protected IActivityManager More ...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;
}
};

再附上ActivityManagerNative的完整源码地址:[源码](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/app/ActivityManagerNative.java),有兴趣的可以去阅读一下。

从上面的分析可以知道,Activity由ActivityManagerNative.getDefault()来启动。而ActivityManagerNative.getDefault()实际上是AMS,因此Activity的启动过程又转移到了AMS中,为了继续分析这个过程,只需要查看AMS的startActivity方法即可,在分析AMS的startActivity方法之前,我们先回过头来看一下Instrumentation的execStartActivity方法,其中有一行代码:checkStartActivityResult(result,intent),直观上看起来这个方法的作用像是在检查启动Activity的记过,他的具体实现如下所示:

/package/ 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");
        default:
            throw new AndroidRuntimeException("Unknown error code "
                    + res + " when starting " + intent);
    }
}
从上面的代码可以看出,checkStartActivityResult的作用很明显,就是检查启动Activity的结果,当无法正确启动一个Activity时,这个方法会抛出异常信息,其中最熟悉不过的就是"unable to find expliit activity class; have you declared this activity in your androidmainfest.xml"这个异常我就不说了,你懂的。

接着我们继续分析AMS的startActivity方法,如下所示:

public final int More ...startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode,
startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
}

public final int More ...startActivityAsUser(IApplicationThread caller, String callingPackage,
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, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
null, null, options, userId);
}

可以看出,Activity的启动过程又转移到了ActivityStackSupervisor的startActivityMayWait方法中了。在startActivityMayWait中又调用了startActivityLocked方法,接着startActivityLocked又调用了ActivityStack的resumeTopActivityiesLocked方法,这个时候启动过程已经从ActivityStackSupervisor转移到了ActivityStack。

ActivityStack的resumeTopActivitiesLocked方法的实现如下所示:

final boolean More ...resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (inResumeTopActivity) {
// Don't even start recursing.
return false;
}

    boolean result = false;
    try {
        // Protect against recursion.
        inResumeTopActivity = true;
        result = resumeTopActivityInnerLocked(prev, options);
    } finally {
        inResumeTopActivity = false;
    }
    return result;
}
从上面的代码可以看出,resumeTopActivityLocked调用了resumeTopActivityInnerLocked方法,resumeTopActivityInnerLocked方法又调用了ActivityStackSupervisor的satrtSpecificActivityLocked方法,satrtSpecificActivityLocked的源码如下:

void More ...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);
}
从上面的代码可以看出,satrtSpecificActivityLocked方法调用了realStartActivityLocked方法,为了更清晰的说明Activity的启动过程在ActivityStatckSupervisor和ActivityStack之间的传递顺序,下面给出一张流程图。
![image.png](https://upload-images.jianshu.io/upload_images/5272505-5da279e97763d4df.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在ActivityStackSupervisor的realStartActivityLocked方法中 又如下 一段代码:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
results, newIntents, !andResume, mService.isNextTransitionForward(),
profilerInfo);

这段代码很重要,其中app.thread的类型为IApplicationThread,IApplicationThread的声明如下:

[查看源码](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.0.0_r1/android/app/IApplicationThread.java#IApplicationThread)

因为他继承了IInterface接口,所以他是一个Binder类型的接口,从IApplicationThread声明的接口方法中可以看出,其内部包含了大量启动,停止Activity 的接口,此外还包含了启动和停止服务的接口,从接口的方法的命名可以猜测,IApplicationThread这个Binder接口的实现者完成了大量和Activity以及Service启动停止相关的功能。

那么IApplicationThread的实现者到底是什么?答案就是ActivityThread中的内部类ApplicationThread,洗面来看ApplicationThread的定义:

private class More ...ApplicationThread extends ApplicationThreadNative

public abstract class More ...ApplicationThreadNative extends Binder
implements IApplicationThread

可以看出,ApplicationThread继承了ApplicationThreadNative,而ApplicationThreadNative则继承了Binder并实现了IApplicationThread接口。如果读者还记得系统的AIDL文件自动生成的代码,就会发现ApplicationThreadNative的作用其实和系统为AIDL文件生成的类是一样的。

在ApplicationThreadNative的内部,还有一个ApplicationThreadProxy类,这个类的实现如下所示,其实这个内部类也是系统为AIDL文件自动生成的代理类。所以ApplicationThreadNative就是IApplicationThread的实现者,由于ApplicationThreadNative被系统定义为抽象类,所以ApplicationThread就成了IApplicationThread的最终实现者了。

class More ...ApplicationThreadProxy implements IApplicationThread {
private final IBinder mRemote;

 public More ...ApplicationThreadProxy(IBinder remote) {
     mRemote = remote;
 }
 
 public final IBinder More ...asBinder() {
     return mRemote;
 }
 
 public final void More ...schedulePauseActivity(IBinder token, boolean finished,
         boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
     Parcel data = Parcel.obtain();
     data.writeInterfaceToken(IApplicationThread.descriptor);
     data.writeStrongBinder(token);
     data.writeInt(finished ? 1 : 0);
     data.writeInt(userLeaving ? 1 :0);
     data.writeInt(configChanges);
     data.writeInt(dontReport ? 1 : 0);
     mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
             IBinder.FLAG_ONEWAY);
     data.recycle();
 }

 public final void More ...scheduleStopActivity(IBinder token, boolean showWindow,
         int configChanges) throws RemoteException {
     Parcel data = Parcel.obtain();
     data.writeInterfaceToken(IApplicationThread.descriptor);
     data.writeStrongBinder(token);
     data.writeInt(showWindow ? 1 : 0);
     data.writeInt(configChanges);
     mRemote.transact(SCHEDULE_STOP_ACTIVITY_TRANSACTION, data, null,
             IBinder.FLAG_ONEWAY);
     data.recycle();
 }

...
}

绕了一大圈,Activity的启动过程最终回到了ApplicationThread中,ApplicationThread通过scheduleLaunchActivity方法来启动Activity,代码如下:

public final void More ...scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
IVoiceInteractor voiceInteractor, int procState, Bundle state,
PersistableBundle persistentState, List pendingResults,
List pendingNewIntents, boolean notResumed, boolean isForward,
ProfilerInfo profilerInfo) {

         updateProcessState(procState, false);

         ActivityClientRecord r = new ActivityClientRecord();

         r.token = token;
         r.ident = ident;
         r.intent = intent;
         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;

         updatePendingConfiguration(curConfig);

         sendMessage(H.LAUNCH_ACTIVITY, r);
    }
接下来看一下Handler H对消息的处理,如下所示:

private class More ...H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;

public void More ...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;
            case RELAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                handleRelaunchActivity(r);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
            case PAUSE_ACTIVITY:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                        (msg.arg1&2) != 0);
                maybeSnapshot();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
               break;

....

}

从Handler H对“LAUNCH_ACTIVITY”这个消息的处理可以知道,Activity的启动过程 由ActivityThread的handleLaunchActivity方法实现,他的源码如下:

private void handleLaunceActivity(ActivityClientRecord r,Iintent customIntent){
...
if(localLOGV)Slog.v(TAG,"Handling launch of"+r);

Activity a=performLaunchActivity(r,customIntent);

if(a!=null){
r.createdConfig=new Configuration(mConfiguration);
Bundle oldState=r.statr;
handleResumeActivity(r.token,false,r.isForward,!r.activity.mFinished&&!r. startsNotResumed);
...
}
...
}

从上面的源码可以看出,perforLaunchActivity方法最终完成了Activity对象的创建和启动过程,并且ActivityThread通过handleResumeActivity方法来调用被启动Activity的onResume这以生命周期方法。

perforLaunchActivity这个方法主要完成了如下几件事情:

## 1.从ActivityClientRecord中获取待启动的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);
}
}

至于Instrumentation的newActivity,他的实现比较简单,就是通过类加载器来创建Activity对象:

public Activity More ...newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}

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

public Application More ...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);
             }
         }
     }
从makeApplication的实现可以看出,如果Application已经被创建过了,那么就不会再重复创建了,这也意味着一个应用只有一个Application对象,Application对象的创建也是通过Instrumentation来完成,这个过程和Activity的创建一样,都是通过类加载器来实现的,Application创建完毕后,系统会通过Instrumentation的callApplicationOnCreate来调用Application的onCreate方法。

## 4.创建ContextImpl对象并通过Activity的attach方法来完成一些重要的数据初始化:

ContextImpl是一个很重要的数据结构,他是Context的具体实现,Context中的大部分逻辑都是由ContextImpl来完成的。ContxetImpl是通过Activity的attach的方法和Activity建立关联的,除此之外,在attach方法中Activity还会完成Window的创建并建立自己和Window的关联,这样当Window接受到外部输入事件后,就可以将事件传递给Acivity

## 5.调用Activity的onCreate方法

mInstrumentation。callActivityOnCreate(activity,r.state),由于Activity的onCreate已经被调用,这也意味着Activity已经完成了整个启动过程。

你可能感兴趣的:(四大组件的工作过程探索(一))