Android开发艺术探索 - 第9章 四大组件的工作过程
1.Activity启动过程 ref
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {if (mParent == null) {options = transferSpringboardActivityOptions(options);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());}
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {...try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess(who);int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);checkStartActivityResult(result, intent);
public static void checkStartActivityResult(int res, Object intent) {if (!ActivityManager.isStartResultFatalError(res)) {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);
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,boolean validateIncomingUser) {enforceNotIsolatedCaller("startActivity");userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");// TODO: Switch to user app stacks here.return mActivityStartController.obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setMayWait(userId).execute();
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,r.persistentState, results, newIntents, mService.isNextTransitionForward(),profilerInfo));
...
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();transaction.schedule();if (!(client instanceof Binder)) {// If client is not an instance of Binder - it's a remote call and at this point it is// safe to recycle the object. All objects used for local calls will be recycled after// the transaction is executed on client in ActivityThread.transaction.recycle();}
}
// ClientTransaction#schedule
public void schedule() throws RemoteException {mClient.scheduleTransaction(this);
}
// ActivityThread$ApplicationThread#scheduleTransaction
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {ActivityThread.this.scheduleTransaction(transaction);
}
而其scheduleTransaction的实现则非常简单,直接发送了一个Message交由Handler处理:
// ClientTransactionHandler#scheduleTransaction
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {transaction.preExecute(this);sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
Handler中执行了mTransactionExecutor.execute(transaction);
case EXECUTE_TRANSACTION:final ClientTransaction transaction = (ClientTransaction) msg.obj;mTransactionExecutor.execute(transaction);if (isSystem()) {// Client transactions inside system process are recycled on the client side// instead of ClientLifecycleManager to avoid being cleared before this// message is handled.transaction.recycle();}// TODO(lifecycler): Recycle locally scheduled transactions.break;
在TransactionExecutor的excute中,调用executeCallbacks执行具体的事务ClientTransactionItem:
public void execute(ClientTransaction transaction) {final IBinder token = transaction.getActivityToken();log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);executeCallbacks(transaction);executeLifecycleState(transaction);mPendingActions.clear();log("End resolving transaction");
}@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {final List<ClientTransactionItem> callbacks = transaction.getCallbacks();if (callbacks == null) {// No callbacks to execute, return early.return;}log("Resolving callbacks");final IBinder token = transaction.getActivityToken();ActivityClientRecord r = mTransactionHandler.getActivityClient(token);...final int size = callbacks.size();for (int i = 0; i < size; ++i) {final ClientTransactionItem item = callbacks.get(i);...item.execute(mTransactionHandler, token, mPendingActions);item.postExecute(mTransactionHandler, token, mPendingActions);
@Override
public void execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,mPendingResults, mPendingNewIntents, mIsForward,mProfilerInfo, client);client.handleLaunchActivity(r, pendingActions, null /* customIntent */);Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
在ActivityThread的ActivityThread方法中,最终调用到了performLaunchActivity方法:
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {...final Activity a = performLaunchActivity(r, customIntent);
进入performLaunchActivity方法,开始创建Activity:
- 从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); }
- 创建ContextImpl,通过Instrumentation#newActivity方法使用ClassLoader创建Activity对象:
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {java.lang.ClassLoader cl = appContext.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);}
- 通过LoadedApk#makeApplication方法尝试创建Application对象。如果Application已经创建过了,则不会再次创建,所以一个应用只有一个Application。而创建过程同Activity也是通过Instrumentation#newApplication方法使用ClassLoader创建,创建完成后,通过callApplicationOnCreate回调Application#onCreate方法:
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {if (mApplication != null) {return mApplication;}try {java.lang.ClassLoader cl = getClassLoader();if (!mPackageName.equals("android")) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"initializeJavaContextClassLoader");initializeJavaContextClassLoader();Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);...if (instrumentation != null) {try {instrumentation.callApplicationOnCreate(app);
- 通过Activity#attach方法来完成重要数据的初始化,与ContextImpl的关联,以及Window创建和与Window的关联。
appContext.setOuterContext(activity);
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, window, r.configCallback);
- 调用Activity#onCreate方法
通过mInstrumentation.callActivityOnCreate(activity, r.state);
回调Activity#onCreate。至此,Activity创建完毕。
2.Service
- 启动过程
Activity#startService->ContextWrapper#startService,这里的mBase,即是创建Activity时,关联的ContextImpl对象。ContextWrapper的实现大部分由ContextImpl完成,典型的桥接模式:
@Override
public ComponentName startService(Intent service) {return mBase.startService(service);
}
ContextImpl#startService->startServiceCommon,同Activity,同样会通过AMS去执行startService操作:
```
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,UserHandle user) {try {validateServiceIntent(service);service.prepareToLeaveProcess(this);ComponentName cn = ActivityManager.getService().startService(mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground,getOpPackageName(), user.getIdentifier());
```
AMS#startService中调用mService的startServiceLocked方法,这个mService的类型是ActiveService,他的作用是辅助AMS进行service的启动/绑定/停止:
@Override
public ComponentName startService(IApplicationThread caller, Intent service,String resolvedType, boolean requireForeground, String callingPackage, int userId)throws TransactionTooLargeException {...try {res = mServices.startServiceLocked(caller, service,resolvedType, callingPid, callingUid,requireForeground, callingPackage, userId);
startServiceLocked->startServiceInnerLocked,传递的ServiceRecord描述了一个service记录,其一直贯穿整个service的启动过程。然后调用bringUpServiceLocked:
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {ServiceState stracker = r.getTracker();if (stracker != null) {stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);}r.callStart = false;synchronized (r.stats.getBatteryStats()) {r.stats.startRunningLocked();}String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
bringUpServiceLocked->realStartServiceLocked,其中主要关注两个调用:首先同Activity,远程调用了ApplicationThread#scheduleCreateService创建service,回调onCreate方法;然后通过sendServiceArgsLocked方法来调用其他方法,如onStartCommand方法:
private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app, boolean execInFg) throws RemoteException {...try {...app.thread.scheduleCreateService(r, r.serviceInfo,mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),app.repProcState);...sendServiceArgsLocked(r, execInFg, true);
ApplicationThread#scheduleCreateService,同Activity,也是发送Message给Handler处理:
public final void scheduleCreateService(IBinder token,ServiceInfo info, CompatibilityInfo compatInfo, int processState) {updateProcessState(processState, false);CreateServiceData s = new CreateServiceData();s.token = token;s.info = info;s.compatInfo = compatInfo;sendMessage(H.CREATE_SERVICE, s);
}
Handler异步回调handleCreateService创建service:
- 通过ClassLoader创建service:
LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo); Service service = null; try {java.lang.ClassLoader cl = packageInfo.getClassLoader();service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent); } catch (Exception e) {if (!mInstrumentation.onException(service, e)) {throw new RuntimeException("Unable to instantiate service " + data.info.name+ ": " + e.toString(), e);} }
- 创建ContextImpl,并通过service的attach方法进行关联;视情况创建Application实例,同Activity;回调service的onCreate方法;最后,将service实例存储到ArrayMap中:
ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service);Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app,ActivityManager.getService()); service.onCreate(); mServices.put(data.token, service);
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
service创建完毕,之后会被远程调用handleServiceArgs方法,进而回调onStartCommand。
2. 绑定过程
Activity#bindService->ContextWrapper#bindService->ContextWrapper#bindServiceCommon,首先,通过LoadedApk#getServiceDispatcher方法,根据ServiceConnection得到IServiceConnection接口的Binder对象,因为bind操作可能是跨进程,所以要使用Binder支持IPC。然后调用AMS的远程bindService方法:
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.IServiceConnection sd;...if (mPackageInfo != null) {sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);...try {...int res = ActivityManager.getService().bindService(mMainThread.getApplicationThread(), getActivityToken(), service,service.resolveTypeIfNeeded(getContentResolver()),sd, flags, getOpPackageName(), user.getIdentifier());
获得IServiceConnection接口Binder对象的过程:每个Context对应一个map,存储了<ServiceConnection,LoadedApk.ServiceDispatcher>的map,通过这个ServiceDispatcher的getIServiceConnection方法,可以得到其内部类InnerConnection的实例,该类实现了IServiceConnection接口:
public final IServiceConnection getServiceDispatcher(ServiceConnection c,Context context, Handler handler, int flags) {synchronized (mServices) {LoadedApk.ServiceDispatcher sd = null;ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);if (map != null) {if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);sd = map.get(c);}if (sd == null) {sd = new ServiceDispatcher(c, context, handler, flags);if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);if (map == null) {map = new ArrayMap<>();mServices.put(context, map);}map.put(c, sd);} else {sd.validate(context, handler);}return sd.getIServiceConnection();}
}
AMS#bindService->ActiveServices#bindServiceLocked->bringUpServiceLocked->realStartServiceLocked,之后的流程同创建Service,会通过ApplicationThread来完成service创建以及onCreate方法的回调。另外,realStartServiceLocked方法中,会调用requestServiceBindingsLocked(r, execInFg)
方法,根据record执行app.thread.scheduleBindService
来进行onBind回调:
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)throws TransactionTooLargeException {for (int i=r.bindings.size()-1; i>=0; i--) {IntentBindRecord ibr = r.bindings.valueAt(i);if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {break;}}
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,boolean execInFg, boolean rebind) throws TransactionTooLargeException {...if ((!i.requested || rebind) && i.apps.size() > 0) {try {bumpServiceExecutingLocked(r, execInFg, "bind");r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,r.app.repProcState);
在ActivityThread中,同样是通过Handler,最终执行到其handleBindService方法。回调service的onBind方法,onBind返回一个Binder对象,通过AMS#publishService将其传递给client,client的onServiceConnected接收到,bind操作完成:
// ApplicationThread#scheduleBindService
public final void scheduleBindService(IBinder token, Intent intent,boolean rebind, int processState) {...sendMessage(H.BIND_SERVICE, s);
}
private void handleBindService(BindServiceData data) {Service s = mServices.get(data.token);if (DEBUG_SERVICE)Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);if (s != null) {try {data.intent.setExtrasClassLoader(s.getClassLoader());data.intent.prepareToEnterProcess();try {if (!data.rebind) {IBinder binder = s.onBind(data.intent);ActivityManager.getService().publishService(data.token, data.intent, binder);} else {s.onRebind(data.intent);ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);}
client接收Binder的具体过程:AMS#publishService->ActiveServices#publishServiceLocked,其关键代码c.conn.connected(r.name, service, false)
,c.conn即IServiceConnection接口,对应之前的ServiceDispatcher.InnerConnection类型:
public void connected(ComponentName name, IBinder service, boolean dead)throws RemoteException {LoadedApk.ServiceDispatcher sd = mDispatcher.get();if (sd != null) {sd.connected(name, service, dead);}
}
进而调用ServiceDispatcher#connected。这里的mActivityThread的类型为Handler,他是在创建ServiceDispatcher时,传递进来的ActivityThread的Handler实例。所以最终会通过该Handler在主线程执行RunConnection:
public void connected(ComponentName name, IBinder service, boolean dead) {if (mActivityThread != null) {mActivityThread.post(new RunConnection(name, service, 0, dead));} else {doConnected(name, service, dead);}}
RunConnection#run则执行了ServiceDispatcher#doConnected,client的onServiceConnected被调用:
public void doConnected(ComponentName name, IBinder service, boolean dead) {...// If there is a new viable service, it is now connected.if (service != null) {mConnection.onServiceConnected(name, service);}
3.BroadcastReceiver
- 注册过程
静态注册,同其他三大组件,在应用安装时通过PMS(PackageManagerService)解析并注册。
动态注册过程如下。
ContextWrapper#registerReceiver->ContextImpl#registerReceiver->registerReceiverInternal。与bind service类似,也是先得到一个供远程AMS调用的Binder实例,类型为IIntentReceiver,实现类为ReceiverDispatcher.InnerReceiver;之后调用AMS#registerReceiver方法:
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,IntentFilter filter, String broadcastPermission,Handler scheduler, Context context, int flags) {IIntentReceiver rd = null;...rd = new LoadedApk.ReceiverDispatcher(receiver, context, scheduler, null, true).getIIntentReceiver();}}try {final Intent intent = ActivityManager.getService().registerReceiver(mMainThread.getApplicationThread(), mBasePackageName, rd, filter,broadcastPermission, userId, flags);
AMS#registerReceiver关键代码,将InnerReceiver远程Binder和IntentFilter对象存储起来:
public Intent registerReceiver(IApplicationThread caller, String callerPackage,IIntentReceiver receiver, IntentFilter filter, String permission, int userId,int flags) {...mRegisteredReceivers.put(receiver.asBinder(), rl);...BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,permission, callingUid, userId, instantApp, visibleToInstantApps);if (rl.containsFilter(filter)) {Slog.w(TAG, "Receiver with filter " + filter+ " already registered for pid " + rl.pid+ ", callerPackage is " + callerPackage);} else {rl.add(bf);if (!bf.debugCheck()) {Slog.w(TAG, "==> For Dynamic broadcast");}mReceiverResolver.addFilter(bf);
- 发送接收过程
从广播的发送开始。
ContextWrapper#sendBroadcast->ContextImpl#sendBroadcast->AMS#broadcastIntent->AMS#broadcastIntentLocked。首先,为其Intent中添加Intent.FLAG_EXCLUDE_STOPPED_PACKAGES
,从Android 5.0起,默认不会向已经停止的app发送广播。如果希望向停止的app发送广播,添加Intent.FLAG_INCLUDE_STOPPED_PACKAGES
即可,当两个flag同时存在,以include为准:
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
之后,broadcastIntentLocked的主要工作就是,根据intent-filter查找出匹配的receiver,终将满足的receiver添加到BroadcastRecord中,接着执行scheduleBroadcastsLocked方法发送广播:
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {...final BroadcastQueue queue = broadcastQueueForIntent(intent);BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,resultCode, resultData, resultExtras, ordered, sticky, false, userId);...if (!replaced) {queue.enqueueParallelBroadcastLocked(r);queue.scheduleBroadcastsLocked();}registeredReceivers = null;NR = 0;
}
...
if ((receivers != null && receivers.size() > 0)|| resultTo != null) {BroadcastQueue queue = broadcastQueueForIntent(intent);BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,resultData, resultExtras, ordered, sticky, false, userId);...} else {queue.enqueueOrderedBroadcastLocked(r);queue.scheduleBroadcastsLocked();}
BroadcastQueue#scheduleBroadcastsLocked只是发出一个message:
public void scheduleBroadcastsLocked() {if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["+ mQueueName + "]: current="+ mBroadcastsScheduled);if (mBroadcastsScheduled) {return;}mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));mBroadcastsScheduled = true;}
之后,Handler调用processNextBroadcast->processNextBroadcastLocked。以无序广播为例,取出BroadcastRecord,遍历其中的receiver,调用deliverToRegisteredReceiverLocked方法向target发出广播:
// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {r = mParallelBroadcasts.remove(0);...for (int i=0; i<N; i++) {Object target = r.receivers.get(i);if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,"Delivering non-ordered on [" + mQueueName + "] to registered "+ target + ": " + r);deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
deliverToRegisteredReceiverLocked->performReceiveLocked,最终调用了app.thread.scheduleRegisteredReceiver,回到了ApplicationThread:
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,Intent intent, int resultCode, String data, Bundle extras,boolean ordered, boolean sticky, int sendingUser) throws RemoteException {// Send the intent to the receiver asynchronously using one-way binder calls.if (app != null) {if (app.thread != null) {// If we have an app thread, do the call through that so it is// correctly ordered with other one-way calls.try {app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,data, extras, ordered, sticky, sendingUser, app.repProcState);
ApplicationThread#scheduleRegisteredReceiver->IIntentReceiver.performReceive,IIntentReceiver即为注册receiver时,创建的Binder对象实例,类型为ReceiverDispatcher.InnerReceiver:
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,int resultCode, String dataStr, Bundle extras, boolean ordered,boolean sticky, int sendingUser, int processState) throws RemoteException {updateProcessState(processState, false);receiver.performReceive(intent, resultCode, dataStr, extras, ordered,sticky, sendingUser);}
InnerReceiver#performReceive->ReceiverDispatcher#performReceive,该方法中,通过
创建一个Runnable,将调用onReceive的操作,交给mActivityThread即Handler去执行,该Handler就是ActivityThread中的H:
public void performReceive(Intent intent, int resultCode, String data,Bundle extras, boolean ordered, boolean sticky, int sendingUser) {final Args args = new Args(intent, resultCode, data, extras, ordered,sticky, sendingUser);...if (intent == null || !mActivityThread.post(args.getRunnable())) {
最终,onReceive在主线程中被调用:
try {ClassLoader cl = mReceiver.getClass().getClassLoader();intent.setExtrasClassLoader(cl);intent.prepareToEnterProcess();setExtrasClassLoader(cl);receiver.setPendingResult(this);receiver.onReceive(mContext, intent);
4.ContentProvider
应用启动流程:
- VM调用ActivityThread的main方法。
- main方法中,会创建ActivityThread的实例,然后调用其attach方法;同时会创建主线程的消息队列。
- attch方法中,会调用AMS的远程方法attachApplication,将其ApplicationThread传递给AMS。ApplicationThread是个Binder对象,用于ActivityThread和AMS的通信。
- 在AMS的attachApplication方法中,会远程调用ApplicationThread的bindApplication方法,ApplicationThread转而交由ActivityThread的Handler处理,具体方法为handleBindApplication。
- 在handleBindApplication方法中,会创建Application对象,并加载ContentProvider。加载过程发生在回调Application的onCreate方法之前。
ContentProvider可以通过android:multiProcess
来为其指定多实例,在每个调用者的进程中,都存在一个CopntentProvider实例。不过大部分的使用场景,ContentProvider为单实例。
访问ContentProvider使用的ContentResolver是个抽象类,getContentResolver得到的实例实际为ContextImpl.ApplicationContentResolver。当通过其四个方法访问ContentProvider时,其所在进程未启动,则会触发其创建,并伴随着ContentProvider的创建。这里以query为例。
ContentResolver#query首先调用了acquireUnstableProvider方法,来获取一个IContentProvider实例。然后调用了子类的acquireUnstableProvider方法,这里的mMainThread即是ActivityThread:
@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {return mMainThread.acquireProvider(c,ContentProvider.getAuthorityWithoutUserId(auth),resolveUserIdFromAuthority(auth), false);
}
ActivityThread#acquireProvider,首先会判断目标provider是否存在,如果存在直接返回;如果不存在则通过AMS#getContentProvider方法去创建他,最后通过installProvider修改引用计数:
public final IContentProvider acquireProvider(Context c, String auth, int userId, boolean stable) {final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);if (provider != null) {return provider;}...try {synchronized (getGetProviderLock(auth, userId)) {holder = ActivityManager.getService().getContentProvider(getApplicationThread(), auth, userId, stable);...// Install provider will increment the reference count for us, and break// any ties in the race.holder = installProvider(c, holder, holder.info,true /*noisy*/, holder.noReleaseNeeded, stable);return holder.provider;}
AMS#getContentProvider->AMS#getContentProviderImpl->startProcessLocked->startProcess,首先创建目标进程。具体为调用了Process.start方法:
private ProcessStartResult startProcess(String hostingType, String entryPoint,ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,String seInfo, String requiredAbi, String instructionSet, String invokeWith,long startTime) {...startResult = Process.start(entryPoint,app.processName, uid, uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, invokeWith,new String[] {PROC_START_SEQ_IDENT + app.startSeq});
新进程启动后,其入口方法为ActivityThread#main:
public static void main(String[] args) {...ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}
如前述,Activity#attach->AMS#attachApplication->AMS#attachApplicationImpl->ApplicationThread#bindApplication,然后交由ActivityThread的Handler处理,具体在handleBindApplication方法:
首先,创建ContextImpl和Instrumentation:
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);try {final ClassLoader cl = instrContext.getClassLoader();mInstrumentation = (Instrumentation)cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {throw new RuntimeException("Unable to instantiate instrumentation "+ data.instrumentationName + ": " + e.toString(), e);
}final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
创建Application:
Application app;
...
try {// If the app is being launched for full backup or restore, bring it up in// a restricted environment with the base application class.app = data.info.makeApplication(data.restrictedBackupMode, null);...mInitialApplication = app;
创建ContentProvider,并调用其onCreate方法。
- installContentProviders方法中,遍历当前进程的ProviderInfo列表,一一调用其installProvider方法来启动他们。然后将ContentProvider发布到AMS当中,AMS会把其存储在ProviderMap中,下次调用便可直接获得provider实例:
installContentProviders(app, data.providers);
private void installContentProviders(Context context, List<ProviderInfo> providers) {final ArrayList<ContentProviderHolder> results = new ArrayList<>();for (ProviderInfo cpi : providers) {if (DEBUG_PROVIDER) {StringBuilder buf = new StringBuilder(128);buf.append("Pub ");buf.append(cpi.authority);buf.append(": ");buf.append(cpi.name);Log.i(TAG, buf.toString());}ContentProviderHolder cph = installProvider(context, null, cpi,false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);if (cph != null) {cph.noReleaseNeeded = true;results.add(cph);}}try {ActivityManager.getService().publishContentProviders(getApplicationThread(), results);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}
}
- provider的具体创建过程在installProvider方法中完成。通过ClassLoader创建provider对象,然后调用其attachInfo回调onCreate方法:
private ContentProviderHolder installProvider(Context context,ContentProviderHolder holder, ProviderInfo info,boolean noisy, boolean noReleaseNeeded, boolean stable) {...try {final java.lang.ClassLoader cl = c.getClassLoader();LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);if (packageInfo == null) {// System startup case.packageInfo = getSystemContext().mPackageInfo;}localProvider = packageInfo.getAppFactory().instantiateProvider(cl, info.name);...localProvider.attachInfo(c, info);
provider创建完成,调用Application的onCreate方法:
try {mInstrumentation.callApplicationOnCreate(app);
至此,ContentProvider创建完成,其进程的Application也创建完成。使用ContentProvider时,实际上是通过获得的IContentProvider接口去执行远程调用,实际类型为ContentProvider.Transport,其query方法:
@Override
public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,@Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {...try {return ContentProvider.this.query(uri, projection, queryArgs,CancellationSignal.fromTransport(cancellationSignal));
调用ContentProvider的query方法,然后通过Binder传递给client,完成了一次调用,其他方法类似。
Android开发艺术探索 - 第9章 四大组件的工作过程相关推荐
- Android开发艺术探索——第七章:Android动画深入分析
Android开发艺术探索--第七章:Android动画深入分析 Android的动画可以分成三种,view动画,帧动画,还有属性动画,其实帧动画也是属于view动画的一种,,只不过他和传统的平移之类 ...
- 《Android开发艺术探索》第9章-四大组件的工作过程读书笔记
目录 1 四大组件的运行状态 2 Activity 的工作过程 2.1 Activity 的启动过程 3 Service 的工作过程 3.1 Service 有哪两种工作状态?这两种状态可以共存吗? ...
- 《Android开发艺术探索》笔记目录
该笔记以<Android开发艺术探索>为基础,结合Android 9.0代码和官方文档,修正了原书中表述不明确和过时的部分,同时加入了大量的个人理解. 13章,14章,15章是总结性的章节 ...
- 《Android开发艺术探索》完结篇
笔记链接: <Android开发艺术探索>之Activity的生命周期和启动模式(一) <Android开发艺术探索>之IPC机制上(二) <Android开发艺术探索& ...
- 《Android开发艺术探索》
序 昨晚准备参考一下 <Android 开发艺术探索>这本书写一个博客 ,但是在家里找了好长时间也找不见 .所以就找了网上的文章 .这本书强烈推荐大家好好读几遍 . <Android ...
- Android开发艺术探索完结篇——天道酬勤
这片文章发布,代表着我已经把本书和看完并且笔记也发布完成了,回忆了一下我看Android群英传,只用了两个月,但是看本书却花了2016年05月04日 - 2018年07月16日,整整两年多,真是惭愧 ...
- Android开发艺术探索之Activity篇总结
本文内容来自<Android开发艺术探索>第一章,个人学习提炼总结,欢迎指正. 1.1典型情况下的生命周期 onCreate():表示Activity正在被创建,初始化布局资源+Activ ...
- Android开发艺术探索——新的征程,程序人生路漫漫!
Android开发艺术探索--新的征程,程序人生路漫漫! 偶尔写点东西分享,但是我还是比较喜欢写笔记,看书,群英传看完了,是学到了点东西,开始看这本更加深入Android的书籍了,不知道适不适合自己, ...
- Android开发艺术探索 读书笔记
啥也不说了,@主席的<Android开发艺术探索>真是业界良心之作,不得不看!感谢主席,膜拜主席!主席主席,我要跟你生猴子!(>^ω^<) 读书笔记中若有任何问题请留言告知,谢 ...
最新文章
- delphi编码规范文档
- pandas 中的函数—— .reset_index()
- Java入门算法(数据结构篇)丨蓄力计划
- 【状压DP】滚榜(P7519)
- ad如何设置pcb板子形状_手把手教你在PCB上添加泪滴
- [密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]49.描述在IPsec和TLS后的基本想法
- java程序员_Java和Python的区别 好程序员帮大家解读
- Django 第十二课 【class meta】
- 【Antlr】修改由Antlr生成的表示式?替换遍历方式?
- 概率论——伯努利和二项随机变量
- springboot 乱码之URLDecoder解析
- Photoshop插件-动作相关概念-ActionList-ActionDescriptor-ActionList-动作执行加载调用删除-PS插件开发
- 2级c语言题库及答案,2019-C语言二级考试题库(含答案)
- 黑马python培训网盘资源
- 【故事编程:Lambda表达式】之最甜的巧克力(二)
- C++算法之-小球问题
- Ubuntu18.04 使用gnome-tweak美化系统主题
- 关于 傅里叶变换 的一些理解(通俗版)
- 计算机组成原理——计算机的运算方法
- 植树节推文如何排版?—135植树节样式上新