第九章四大组件的工作过程(一)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的启动过程,来看图:
- 第九章四大组件的工作过程(一)Activity的工作过程(Android开发艺术探索)
- Android开发艺术探索——第九章:四大组件的工作过程(上)
- 《Android开发艺术探索》第九章四大组件的工作过程小结
- 《Android开发艺术探索》之学习笔记(九)四大组件的工作过程
- 四大组件的工作过程(Android开发艺术探索读书笔记)
- 开发艺术探索 -- 四大组件的工作过程
- 【读书笔记】【Android 开发艺术探索】第 9 章 四大组件的工作过程
- Android四大组件的工作过程(一)-Activity的工作过程
- 四大组件的工作过程探索(一)
- 第九章、 四大组件的工作过程
- 第九章 四大组件的工作过程
- 从源码的角度理解四大组件的工作过程——Android开发艺术探索笔记
- (十七)四大组件的工作过程-Activity
- 四大组件Activity的工作过程
- Service的工作过程(Android开发艺术探索学习笔记)
- 【Android学习】四大组件的工作过程
- Android 四大组件的工作过程
- Android四大组件的工作过程
- Android 跳转到下个Activity并将当前Activity从栈中移除
- java基础16:GUI
- 2种不同形式的跑马灯的实现
- Android杂知识点
- Gitlab简单使用指南
- 第九章四大组件的工作过程(一)Activity的工作过程(Android开发艺术探索)
- SwipeRefreshLayout初次使用——解决无法下拉问题
- 使用TextView/EditText应该注意的地方
- 重定向和转发的区别
- 改变屏幕Brightness(亮度)
- 控件更新Invalidate和postInvalidate的区别
- Android 集成 OpenCV native library
- java基础17:异常
- 排序算法(一):JAVA实现冒泡排序