四大组件的运行状态
Android的四大组件中除了BroadcastReceiver以外,其他三种必须在AndroidMainfest清单文件中注册。对于BroadcastReceiver既可以在AndroidMainfest注册,也可以通过代码来注册。
从调用方式上来说:Activity、Service和BroadcastReceiver需要借助Intent,而ContentProvider则无需借助Intent。
Activity
Activity是一种展示型组件,用于向用户直接的展示一个界面,并且可以接受用户的输入信息从而进行交互。
Service
Service是一种计算型组件,用于在后台执行一系列计算任务。Service本身是运行在UI线程中的,所以做一些耗时计算时,需要开启子线程。Service有两种状态:
1、启动状态
2、绑定状态
BroadcastReceiver
BroadcastReceiver是一种消息型组件,用于在不同的组件乃至不同的应用之间传递消息。
广播注册有两种方式,
动态注册通过Context.registerReceiver()来实现,必须要应用启动才能注册;
静态注册则在AndroidManifest文件中进行,应用安装时会被系统解析,不需要启动应用就可接收广播。
ContentProvider
ContentProvider是一种数据共享型组件,用于向其他组件乃至其他应用共享数据。
本章所讲四大组件的工作过程稍微有些难,需要看源码理解。
Activity的工作过程
比如我们启动一个新的Activity:
startActivity(new Intent(this,ActivityA.class));
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);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
上面这段代码中,mParent代表ActivityGrou。mMainThread.getApplicationThread()这个参数返回的是一个ApplicationThread对象。ApplicationThread又是ActivityThread的内部类。
ApplicationThread继承自ApplicationThreadNative,ApplicationThreadNative继承了Binder又实现了IApplicationThread接口。所以说ApplicationThread本质是一个Binder对象。
public ApplicationThread getApplicationThread()
{
return mAppThread;
}
/**继承自ApplicationThreadNative*/
private class ApplicationThread extends ApplicationThreadNative{}
/**继承自Binder同时实现IApplicationThread */
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread {}
//所以说ApplicationThread 本质上是一个Binder对象。
这里我们来看一个很重要的类ActivityThread,在Activity启动过程中发挥很重要的作用:
public final class ActivityThread {
public static final String TAG = "ActivityThread";
final ApplicationThread mAppThread = new ApplicationThread();
/**ActivityThread的内部类*/
private class ApplicationThread extends ApplicationThreadNative {
/**这里将代码进行了精简*/
@Override
public final void scheduleLaunchActivity(.....) {
/**发送消息启动ACT*/
sendMessage(H.LAUNCH_ACTIVITY, r);
}
}
/***/
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
/**处理消息,调用handleLaunchActivity方法*/
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
}
}
/**获取ApplicationThread 对象*/
public ApplicationThread getApplicationThread(){
return mAppThread;
}
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//这里代码也进行了精简
/**在这里调用了performLaunchActivity方法完成Act的创建和启动*/
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
/**在这里调用ACT的onResume方法*/
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
if (!r.activity.mFinished && r.startsNotResumed) {
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
if (!r.activity.mCalled) {
throw new SuperNotCalledException();
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to pause activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
r.paused = true;
}
} else {
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
}
}
}
}
performLaunchActivity这个方法主要完成了以下几件事情:具体参考源码
1、从ActiivtyClientRecore中获取待启动Activity的组件信息
2、通过Instrumentation的newActiivty方法使用类加载器创建Activity对象
3、通过LoadedApk的makeApplication方法来尝试创建Application对象。
4、创建ContextImpl对象并通过Activity的attach方法来完成一些重要数据的初始化
5、调用Activity的工作过程
我们接着来看mInstrumentation.execStartActivity方法中,启动Activity的真正实现由ApplicationThreadNative.getDefalut()的startActivity方法来完成。ApplicationThreadNative.getDefalut()方法中返回的是IActivityManager接口对象。因此具体实现为AMS。
ActivityManagerService(AMS)继承自ActivityManagerNative,ActivityManagerNative又继承自Binder并且实现了IActivityManager接口,所以AMS本质上也是一个Binder。
/**ActivityManagerNative 抽象类*/
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
static public IActivityManager getDefault() {
return gDefault.get();
}
}
/**ActivityManagerService类 */
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback{
/**精简代码*/
/**在这类调用startActivityAsUser方法*/
@Override
public final int startActivity(IApplicationThread caller, ..., Bundle options) {
return startActivityAsUser(caller, ...,UserHandle.getCallingUserId());
}
/**这里启动调用了ActivityStackSupervisor的startActivityMayWait方法*/
@Override
public final int startActivityAsUser(IApplicationThread caller,..., int userId) {
return mStackSupervisor.startActivityMayWait(caller,..., null);
}
}
这里来看一张整理的图吧:
Service的工作过程
通过Context的startService方法启动一个Service,如下:
Intent it=new Intent(this,MyService.class);
startService(it);
通过Context的bindService方法即可以绑定的方式启动一个Service,如下:
Intent it=new Intent(this,MyService.class);
bindService(it,mServiceConnection,BIND_AUTO_CREATE);
Service的启动过程
Service的启动时从ContextWrapper的startActivity开始的。mBase类型是ContextImpl,Activity被创建时会通过attach方法将一个ContextImpl对象关联起来。
/**mBase类型是ContextImpl,*/
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
在ContextImpl中,startService方法会调用startServiceCommon方法,而startServiceCommon方法又会通过ActivityManagerNative.getDefault()这个对象来启动一个服务。
Service的绑定过程
和Service的启动过程一样,Service的绑定也是从ContextWrapper开始的。ContextImpl的bindService方法最终会调用自己的bindServiceCommen方法。
剩下的过程呢,跟Activity是类似的,就不在具体解释了。可以看源码喽!
BroadcasrReceiver的工作过程
BroadcasrReceiver的工作过程,主要包含两方面的内容,一个是广播的注册过程,另一个是广播的发送和接收过程。
广播的注册过程
广播的注册分为静态注册和动态注册,其中静态注册的广播在应用安装时由系统自动完成注册,具体来说是由PMS(PackageManagerService)来完成整个注册过程的,除了广播意外,其他三大组件也都是在应用安装时由PMS解析并注册的。
广播的动态注册
广播的动态注册是从ContextWrapper的registerReceive方法开始的,和Activity以及Service一样。ContextWrapper并没有做实际的工作,而是将注册过程交给了ContextImpl。
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
ContextImpl的registerReceiver方法调用了自己的registerReceiverInternal方法。
在registerReceiverInternal方法中,系统首先从mPackageInfo获取到了IIntentReceive对象,然后再采用跨进程的凡事向AMS发送广播注册的请求。
之所以采用 IIntentReceive而不是直接采用BroadcasrReceiver,是因为注册过程是一个进程间通讯的过程,而BroadcasrReceive作为Android的一个组件是不能直接跨进程传递的,所以需要通过IIntentReceive来中转。
方法最后返回了ActivityManagerNative.getDefault().registerReceiver()方法,显然注册过程又交给了AMS。在registerReceiver()方法中会把远程的InnerReceiver对象以及IntentFilter对象存储起来,这样就完成广播注册的过程。
广播的发送和接收过程
广播的发送和接收,其本质是一个过程的两个阶段,这里从广播的发送说起:
广播的发送开始于ContextWrapper的sendBroadcast方法,之所以不是Context,是因为Context中的sendBroadcast是一个抽象方法。
和广播的注册过程一样, ContextWrapper的sendBroadcast方法仍然什么都不做,只把事情交给ContextImpl去处理。
1、 ContextImpl也是几乎什么事情都没干,直接向AMS发起了一个异步请求用于发送广播。在AMS的broadcaseIntent方法中去发送广播。
2、 broadcaseIntent中调用了broadcaseIntentLocked方法,broadcaseIntentLocked方法内部,会根据intent-fitter查找出匹配的广播接收者并经过一系列的条件过滤。最终会将满足条件的广播接受者添加到BroadQueue中,接着BroadQueue就会将广播发送给相应的广播接受者。3、BroadQueue的scheduleBroadcasrLocked方法并没有立即发送广播,而是发送完了一个BROADCAST_INTENT_MSG类型的消息,收到消息后会调用processNextBroadcast方法。
4、 processNextBroadcast方法中通过deliverToRegisteredReceiverLocked方法来实现的,它将一个广播发送个一个特定的接收者,内部调用了performReceiveLocked方法来完成具体的发送过程。
5、performReceiveLocked内部又调用了Application的scheduleRegisteredReceiver,通过InnerReceiver实现广播的接收。
.
6、InnerReceiver的performReceive方法会调用LoadedAok.ReceiverDispatcher的PerformReceive方法。
.
7、PerformReceive中会通过ActivityThread的post方法来执行Args中的逻辑。而Args是ActivityThread的一个Handler,在mH的handlerMessage方法中,看到onReceive方法执行了,也就是说已经接收到了广播。
ContentProvider的工作过程
ContentProvider是一种内容共享型组件,它通过Binder向其他组件乃至其他应用提供应用数据。当CotnentProvider所在的进程启动时,ContentProvider会同时启动并被发布到AMS中,这个时候onCreate要先于Application的onCreate而执行。
启动过程
1、 当一个应用启动时,入口方法为ActivityThread的main方法,main方法是一个静态方法。在main方法中会创建ActivityThread的实例并创建主线程的消息队列,然后再ActivityThread的attach方法中会远程调用AMS的attachApplication方法并将ApplicationThread对象提供给AMS。
ApplicationThread是一个Binder对象,它的Binder接口是IApplicationThread,主要用于ApplicationThread和AMS之间的通信。
2、在AMS的attachApplication方法中,会调用ApplicationThread的bindApplication方法,这个过程是跨进程完成的,bindApplication的逻辑会经过ApplicationThread中的mH handler切换到ActivityThread中执行。具体的方法是handlerBindApplication。
3、在handlerBindApplication方法中,ActivityThread会创建Application对象并加载ContentProvider,需要注意的是ActivityThread会先加载ContentProvider,然后再调用Application的onCreate方法。
具体实现过程请参照源码!