Android源码分析 - 回顾Activity启动流程
跟踪Activity启动流程
基于 Android8.0 源码跟踪
Android8/9大同小异,但Android10对activity的管理解耦交给了ATMS。
跟踪目的:ams到底在哪里发起activity的启动的?以及resume等生命周期到底是谁发起的?onResume()之后是哪里发起的界面绘制?
下次任务:
- activity栈管理
- wms、handler与同步屏障、屏幕刷新机制
ZygoteInit
孵化器首先fork一个systemserver,然后进入循环,监听fork需求。
public static void main(String argv[]) {if (startSystemServer) {Runnable r = forkSystemServer(abiList, socketName, zygoteServer);if (r != null) {r.run();return;}}caller = zygoteServer.runSelectLoop(abiList);} catch (Throwable ex) {Log.e(TAG, "System zygote died with exception", ex);throw ex;} finally {zygoteServer.closeServerSocket();}if (caller != null) {caller.run();}
}
fork后的进程进入r.run()或者caller.run(),并退出socket监听,原本的zygote进程,仍然保持在loop()状态。
ZygoteServer
通过socekt连接与监听
Runnable runSelectLoop(String abiList) {while (true) {ZygoteConnection connection = peers.get(i);final Runnable command = connection.processOneCommand(this);}
}
ZygoteConnection
真的在socket监听,同时fork出进程来
Runnable processOneCommand(ZygoteServer zygoteServer) {//socket阻塞获取消息args = readArgumentList();//forkpid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,parsedArgs.appDataDir);//fork返回到两个进程try {//如果pid为0,说明当前返回到子进程if (pid == 0) {// in childzygoteServer.setForkChild();zygoteServer.closeServerSocket();IoUtils.closeQuietly(serverPipeFd);serverPipeFd = null;return handleChildProc(parsedArgs, descriptors, childPipeFd);} else {//回到zygote进程IoUtils.closeQuietly(childPipeFd);childPipeFd = null;handleParentProc(pid, descriptors, serverPipeFd);return null;}} finally {IoUtils.closeQuietly(childPipeFd);IoUtils.closeQuietly(serverPipeFd);}}
如果回到子进程,将会关掉zygoteServer等,并将子进程返回出去。看一下handleChildProc(),在这里会关掉socket,并且
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd) {//关闭socketcloseSocket();//zogyteInit去反射子进程的mainreturn ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,null /* classLoader */);
}
回到zygoteInit,看一下zygoteInit如何返回一个子进程,通过run()来启动子进程
ZygoteInit
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {if (RuntimeInit.DEBUG) {Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");}Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");RuntimeInit.redirectLogStreams();RuntimeInit.commonInit();//初始胡运行环境ZygoteInit.nativeZygoteInit();//启动Binde线程池进程return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}private static final native void nativeZygoteInit();
在这里面,通过jni进入AndroidRuntime.cpp,启动binder线程:
AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{gCurRuntime->onZygoteInit();
}
然后进入到app_main.cpp中进行ProcessState的初始化,以及打开binder线程池等待监听数据。
app_main.cpp
virtual void onZygoteInit()
{sp<ProcessState> proc = ProcessState::self();ALOGV("App process: starting thread pool.\n");proc->startThreadPool();
}
细节不再描述了,在binder中追踪过这部分代码。回到zygoteInit,最后RuntimeInit.applicationInit();来启动应用程序
RuntimeInit
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) {return findStaticMain(args.startClass, args.startArgs, classLoader);
}
反射获取到了 ActivityThread.main(),并封装进一个 Runnable中执行
ActivityThread
- 首先准备Looper
- 然后打开applicationThread,这是一个binder线程
- 通知ams我的main()运行了,你可以通知我开启activity了
public static void main(String[] args) {Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false);//这是核心if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();//拿到的是mH}Looper.loop();
}
看到attach()方法
private void attach(boolean system) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {ViewRootImpl.addFirstDrawHandler();RuntimeInit.setApplicationObject(mAppThread.asBinder());final IActivityManager mgr = ActivityManager.getService();try {//将自己的binder线程,也就是applicationThread,只要不是系统服务,就会暴露给ams,交给它管理自己。即便是我们自己写的service,也是进入到这里,不要和系统服务搞混了mgr.attachApplication(mAppThread);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}else{//...}ViewRootImpl.ConfigChangedCallback configChangedCallback = something;ViewRootImpl.addConfigCallback(configChangedCallback);
}
然后我们就去ams中看看attachApplication做了什么
ActivityManagerService
public final void attachApplication(IApplicationThread thread) {synchronized (this) {int callingPid = Binder.getCallingPid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid);Binder.restoreCallingIdentity(origId);}
}
进入到attachApplicationLocked,我们只关注什么时候发起activity启动通知。
我们发现,首先通过IPC通信,让APP先进行bindApplication,然后才到 ActivityStackSupervisor来通知启动activity
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {ProcessRecord app;//contentproviderList<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;if (providers != null && checkAppInLaunchingProvidersLocked(app)) {Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);msg.obj = app;mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);}//...if (app.instr != null) {thread.bindApplication();} else {thread.bindApplication();}//activity栈管理if (normalMode) {try {//通知activity栈管理者,我开了application了,后续你看着办(把任务交给了stack管理者if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}//一些对service、broadcast等的检查return true;
}
在开启activity之前,需要先对application做一个启动处理,application的启动应当在contentprovider之后,activity,service,receiver之前。这里的IApplicationThread是一个aidl,也就是远程服务。我们知道他是一个binder实体。其实就是通过binderproxy来远程IPC调用到app进程的applicationThread的方法:
ApplicationThread in ActivityThread
果然,这个ApplicationThread是一个binder实体,也就是Stub。我们关注到bindApplication方法:
private class ApplicationThread extends IApplicationThread.Stub {public final void bindApplication() {//一系列的参数设置AppBindData data = new AppBindData();data.processName = processName;data.appInfo = appInfo;data.providers = providers;data.instrumentationName = instrumentationName;data.instrumentationArgs = instrumentationArgs;//...data.buildSerial = buildSerial;//最后通过handler通知给mHsendMessage(H.BIND_APPLICATION, data);// mH.sendMessage(msg);}
}
我们关注到mH处理这个 BIND_APPLICATION 消息,在mH的handleMessage的switch case分支中,是这样的
case BIND_APPLICATION:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;
handleBindApplication()方法特别长,我们看重点:
private void handleBindApplication(AppBindData data) {//版本检查if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {StrictMode.enableDeathOnNetwork();}if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {StrictMode.enableDeathOnFileUriExposure();}//开启HttpProxy等操作。。。//创建上下文final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);updateLocaleListFromAppContext(appContext,mResourcesManager.getConfiguration().getLocales());// 反射获取Instrumentation,用来调度四大组件if (ii != null) {final ApplicationInfo instrApp = new ApplicationInfo();ii.copyTo(instrApp);instrApp.initForUser(UserHandle.myUserId());final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,appContext.getClassLoader(), false, true, false);final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);try {//获取到Instrumentationfinal 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);} else {mInstrumentation = new Instrumentation();}//开始进入生命周期,首先开启contentprovider,然后开启application.onCreate()!!!Application app;try {mInitialApplication = app;//开启contentproviderinstallContentProviders(app, data.providers);//Instrumentation的oncreatemInstrumentation.onCreate(data.instrumentationArgs);//application的onCreate()回调mInstrumentation.callApplicationOnCreate(app);} finally {//...}// 预加载文字资源。。
}
看完Application的初始化,我们回到AMS,它接着又通知了 ActivityStackSupervisor.attachApplicationLocked().
整个Android系统的Activity都被AMS管理(Android10之后ATM管理),但最终activity的栈管理,都是交给ActivityStackSupervisor来做的。在栈中,所有Activity都以ActivityRecord的形式存在。
其中真正启动activity的语句是:realStartActivityLocked()
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {final String processName = app.processName;boolean didSomething = false;for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {final ActivityStack stack = stacks.get(stackNdx);if (!isFocusedStack(stack)) {continue;}stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);final ActivityRecord top = stack.topRunningActivityLocked();final int size = mTmpActivityList.size();for (int i = 0; i < size; i++) {final ActivityRecord activity = mTmpActivityList.get(i);if (activity.app == null && app.uid == activity.info.applicationInfo.uid&& processName.equals(activity.processName)) {try {//开启activityif (realStartActivityLocked(activity, app,top == activity /* andResume */, true /* checkConfig */)) {didSomething = true;}} catch (RemoteException e) {Slog.w(TAG, "Exception in new application when starting activity "+ top.intent.getComponent().flattenToShortString(), e);throw e;}}}}}if (!didSomething) {ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);}return didSomething;
}
我们进入到 realStartActivityLocked来看看怎么启动的activity
ActivityStackSupervisor
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException {try {r.startFreezingScreenLocked(app, 0);// schedule launch ticks to collect information about slow apps.r.startLaunchTickingLocked();r.app = app;//app进程,记录其activity集合//在ProcessRecord中,是这样的:final ArrayList<ActivityRecord> activities = new ArrayList<>();int idx = app.activities.indexOf(r);if (idx < 0) {app.activities.add(r);}try {//如果activity本就有,那么就通过newIntentif (andResume) {results = r.results;newIntents = r.newIntents;}//如果这是个HomeActivity,也就是<Main>if (r.isHomeActivity()) {// Home process is the root process of the task.mService.mHomeProcess = task.mActivities.get(0).app;};//这里真正的发起了 Activity的启动app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,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, !andResume,mService.isNextTransitionForward(), profilerInfo);} catch (RemoteException e) {if (r.launchFailed) {//如果启动出错了,结束activitystack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,"2nd-crash", false);return false;}//从集合中去除掉r.launchFailed = true;app.activities.remove(r);throw e;}} r.launchFailed = false;//oncreate后紧接着进行start、resumeif (andResume && readyToResume()) {// As part of the process of launching, ActivityThread also performs// a resume.stack.minimalResumeActivityLocked(r);} return true;
}
我们看到了熟悉的:scheduleLaunchActivity()
,我们看看它是不是发起了activity.onCreate(),同时我们找找onStart、onResume在哪里发起。ActivityStackSupervisor也是通过 IApplicationThread 这个 binder引用远程通知app进程的。也就是通过binder发起transaction(事务)。我们回到ApplicationThread,看一下是怎么处理这个事务的。
ApplicationThread in ActivityThread
public 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) {ActivityClientRecord r = new ActivityClientRecord();//设置一些从ams传递来的消息//通知主线程的mHsendMessage(H.LAUNCH_ACTIVITY, r);
}
ActivityThread的mH就会处理这个 LAUNCH_ACTIVITY 的事件:
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, "LAUNCH_ACTIVITY");Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);} break;
接下来就进入了最最最亲切的 handleLaunchActivity():
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {//这里初始化了windowManagerGlobal,这和WMS有关系WindowManagerGlobal.initialize();//真正的发起activity启动Activity a = performLaunchActivity(r, customIntent);//onCreate之后,如果启动成功,就继续进入onStart和onResumeif (a != null) {r.createdConfig = new Configuration(mConfiguration);reportSizeConfigurations(r);Bundle oldState = r.state;handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);if (!r.activity.mFinished && r.startsNotResumed) {//如果过程出错了,就进入onPauseperformPauseActivityIfNeeded(r, reason);if (r.isPreHoneycomb()) {r.state = oldState;}}} else {//如果启动activity失败,通知ams去finishactivity,即处理activity栈相关工作try {ActivityManager.getService().finishActivity(r.token, Activity.RESULT_CANCELED, null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}
}
我们看到这,发现首先performLaunchActivity()应当是调用onCreate(),如果没问题,接下来就会紧接着handleResumeActivity(),我们接下来就要看,onStart()是在哪个方法里面调用的。我们先看到performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {ActivityInfo aInfo = r.activityInfo;//获取组件名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);}//为activity创建一个contextContextImpl appContext = createBaseContextForActivity(r);Activity activity = null;try {//反射new一个Activity实例出来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);}} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to instantiate activity " + component+ ": " + e.toString(), e);}}//有了activity实例之后try {Application app = r.packageInfo.makeApplication(false, mInstrumentation);//做一些设置if (activity != null) {//windowWindow window = null;if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {window = r.mPendingRemoveWindow;r.mPendingRemoveWindow = null;r.mPendingRemoveWindowManager = null;}//在这里,处理了activity和window、windowmanagerservice的关系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);//如果有intent,交给activity,后面可以通过getIntent()获取//我们发现intent经过了IPC,所以这也表明intent的数据需要是Parcel的,而且不能过大if (customIntent != null) {activity.mIntent = customIntent;}activity.mStartedActivity = false;//设置主题int theme = r.activityInfo.getThemeResource();if (theme != 0) {activity.setTheme(theme);}//在这里调用了 activity.onCreate()if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}//紧接着,调用onStart()r.activity = activity;r.stopped = true;if (!r.activity.mFinished) {activity.performStart();r.stopped = false;}//将activity原有状态进行恢复if (!r.activity.mFinished) {if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}if (!r.activity.mFinished) {activity.mCalled = false;if (r.isPersistable()) {mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnPostCreate(activity, r.state);}if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() +" did not call through to super.onPostCreate()");}}}r.paused = true;mActivities.put(r.token, r);} catch (SuperNotCalledException e) {throw e;} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to start activity " + component+ ": " + e.toString(), e);}}return activity;
}
我们发现,在performLaunchActivity()中,除了调用Activity的onCreate(),还调用了 Activity的onStart()。都是通过 Instrumentation。(我们还会发现Activity的所有生命周期都由Instrumentation发起,所以我们可以通过Instrumentation来hook所有Activity的生命周期)
现在进度就明朗了,接下来就是handleLaunchActivity()中的performResumeActivity()了。我们来看一下他做了什么,之前有一个window出现了,但是还没给他赋值,会在这里完成这个工作吗?因为我们知道onResume()之后,界面就绘制出来了,所以我们接下来的重点不再是追踪onResume()而是来看看界面的绘制是在哪里开始的:
final void handleResumeActivity(IBinder token,boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {ActivityClientRecord r = mActivities.get(token);//调用onResume()r = performResumeActivity(token, clearHide, reason);if (r != null) {final Activity a = r.activity;final int forwardBit = isForward ?WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;// If the window hasn't yet been added to the window manager,// and this guy didn't finish itself or start another activity,// then go ahead and add the window.boolean willBeVisible = !a.mStartedActivity;if (!willBeVisible) {try {willBeVisible = ActivityManager.getService().willActivityBeVisible(a.getActivityToken());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}//如果这个activity不为空,也没结束,但是它的window是空的,换句话说,在onCreate()中并没有进行setContentView(),就会进入到下面的内容。//这里面的几步,本来应该是 setContentView()做得,但是由于之前没有调用setContentView,所以到这里来进行默认处理if (r.window == null && !a.mFinished && willBeVisible) {r.window = r.activity.getWindow();View decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);ViewManager wm = a.getWindowManager();WindowManager.LayoutParams l = r.window.getAttributes();//1. 主动地为activity设置一个decorviewa.mDecor = decor;l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;l.softInputMode |= forwardBit;if (r.mPreserveWindow) {a.mWindowAdded = true;r.mPreserveWindow = false;ViewRootImpl impl = decor.getViewRootImpl();if (impl != null) {impl.notifyChildRebuilt();}}//2. 将这个decorview加到windowmanager中去if (a.mVisibleFromClient) {if (!a.mWindowAdded) {a.mWindowAdded = true;wm.addView(decor, l);} else {a.onWindowAttributesChanged(l);}}} else if (!willBeVisible) {//如果本就不要被展示,就设置为hider.hideForNow = true;}// Get rid of anything left hanging around.cleanUpPendingRemoveWindows(r, false /* force */);//现在window可见了,一切正常,做一些可见情况下的设置if (!r.activity.mFinished && willBeVisible&& r.activity.mDecor != null && !r.hideForNow) {if (r.newConfig != null) {performConfigurationChangedForActivity(r, r.newConfig);r.newConfig = null;}WindowManager.LayoutParams l = r.window.getAttributes();if ((l.softInputMode& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)!= forwardBit) {l.softInputMode = (l.softInputMode& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))| forwardBit;if (r.activity.mVisibleFromClient) {ViewManager wm = a.getWindowManager();View decor = r.window.getDecorView();//windowmanager.updateViewLayout//会调用到WindowManagerGlobal.updateViewLayout()//追进去发现这里仅是更新layoutwm.updateViewLayout(decor, l);}}r.activity.mVisibleFromServer = true;mNumVisibleActivities++;if (r.activity.mVisibleFromClient) {r.activity.makeVisible();}}if (!r.onlyLocalRequest) {r.nextIdle = mNewActivities;mNewActivities = r;//这篇文章大概讲了一下idlehandler的用处://主要用于性能优化,在messagequeue空的时候,执行一些动作。https://www.jianshu.com/p/4c2aa7b7d9b3Looper.myQueue().addIdleHandler(new Idler());}r.onlyLocalRequest = false;// Tell the activity manager we have resumed.if (reallyResume) {try {//通知ams我resume了ActivityManager.getService().activityResumed(token);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}} else {// 如果onresume出了错,告诉ams去finish掉这个activity,进行处理activity栈的该有的工作try {ActivityManager.getService().finishActivity(token, Activity.RESULT_CANCELED, null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}
}
到此。我们跟踪完了。总结流程:
- Zygote孵化出一个app进程,通过ActivityThread.main()进入该进程
- ActivityThread中的applicationThread是一个binder实体,通知给ams
- ams收到后,完成注册。
- ams然后让ActivityStackSupervisor去进行activity栈管理,realStartActivityLocked()去发起activity的启动。
- ActivityStackSupervisor通过applicationThread这个binder代理,远程通知app进程,你可以开启activity了。通过:applicationThread.scheduleLaunchActivity()
- app进程收到消息后,将会接连调用activity的onCreate、onStart、onResume,且设置window相关内容
- 首先实例化一个 activity,为其设置一些信息,例如intent消息等
- activity间的数据传递,除了intent,也可以使用一个全局对象传递,我说这个的意思是,app进程在被zygote幅画出来的时候,也持有了一个VM虚拟机,在其中,各个线程有自己的私有数据区,也有进程的共有数据区。在堆中。同一个进程下,可以直接访问到,而不需要再通过binder来ipc传递。(这部分只是突然想到,还没有确认到底是否合适)
- 然后接连发起生命周期回调,如果中间失败了,将会通知ams,我失败了,你要finishActivity()
- 如果resume也完成了,也会通知ams,我ok了
此外,这次源码阅读发现,AMS的引用并没有持久保存在app进程中!每次都通过ServiceManager去寻找AMS的远程代理!!!
每次读源码都会有收获,下一篇分享activity栈的管理,这关联到activity后续的生命周期。
相关文章:

Android源码分析 - 回顾Activity启动流程
跟踪Activity启动流程 基于 Android8.0 源码跟踪 Android8/9大同小异,但Android10对activity的管理解耦交给了ATMS。 跟踪目的:ams到底在哪里发起activity的启动的?以及resume等生命周期到底是谁发起的?onResume()之后是哪里发起…...

PDMS二次开发(一)——PML类型程序类型与概念
目录前言一、PML类型与概念基础知识变量函数小例子注释PML表达式条件判断语句循环skip和break窗口程序在PDMS菜单栏中添加程序窗口自动定位PML常见控件前言 PDMS二次开发需要.net 有自带的PML语言和C# .net一般通常泛指的是C#语言 模型数据借助.NET的接口可以转换成数据库中的…...

一文揭晓:手机号码归属地api的作用是什么?
随着手机的普及,手机号码的归属地已经成为很多网站和App中调用的重要数据资源。而手机号码归属地API可以帮助开发者快速获取手机号码归属地信息。目前,这种API已经被广泛地使用,用于各种不同的应用场景。这对于用户及开发者来说是非常重要的&…...

电容的结构分类介质封装及应用场景总结
🏡《总目录》 目录 1,概述2,结构分类2.1,固定电容器2.2,可变电容器3,介质分类3.1,无机介质电容器3.2,有机介质电容器3.3,电解电容器3.4,气体介质电容器4,封装分类4.1,直插电容器4.2,贴片电容器5,总结1,概述 电容器作为一种储能元件,在电路中和电阻一样非常常用…...

数据结构初阶——时间复杂度与空间复杂度
时间复杂度与空间复杂度1. 算法效率1.1 如何衡量一个算法的好坏1.2算法的复杂度2.时间复杂度2.1 时间复杂度的概念2.2 大O的渐进表示法2.3常见时间复杂度计算举例实列1:实列2:实列3:实列4:实列5:实列6:实列…...

深度学习之“制作自定义数据”--torch.utils.data.DataLoader重写构造方法。
深度学习之“制作自定义数据”–torch.utils.data.DataLoader重写构造方法。 前言: 本文讲述重写torch.utils.data.DataLoader类的构造方法,对自定义图片制作类似MNIST数据集格式(image, label),用于自己的Pytorc…...

#G. 求约数个数之六
我们先求到区间[1..b]之间的所有约数之和于是结果就等于 [1..b]之间的所有约数之和减去[1..a-1]之间的约数之和很明显这两个问题是同性质的问题,只是右端点不同罢了.明显对于1到N之间的数字,其约数范围也为1到N这个范围内。于是我们可以枚举约数L,当然这…...

如何为Java文件代码签名及添加时间戳?
Java是一种流行的编程语言,大多数组织都使用它来开发业务应用程序。由于其高使用率,攻击者总是试图找到其中的漏洞并基于它利用软件。为了防止此类攻击, 为 Java 文件(.jar)进行代码签名并添加时间戳,可以防…...

Xamarin.Forsm for Android 显示 PDF
背景 某些情况下,需要让用户阅读下发的文件,特别是红头文件,这些文件一般都是使用PDF格式下发,这种文件有很重要的一点就是不能更改。这时候就需要使用原文件进行展示。 Xamarin.Forms Android 中的 WebView 控件是不能直接显示的…...

RK3399平台开发系列讲解(LED子系统篇)LED子系统详解
🚀返回专栏总目录 文章目录 一、设备树编写二、LED子系统2.1、用户态2.2、内核驱动三、驱动代码3.1、平台设备驱动的注册3.2、平台设备驱动的probe四、使用方法沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将详细介绍LED子系统。 一、设备树编写 节点属性添加…...

LeetCode 432. 全 O(1) 的数据结构
LeetCode 432. 全 O(1) 的数据结构 难度:hard\color{red}{hard}hard 题目描述 请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。 实现 AllOneAllOneAllOne 类: AllOne()AllOne()AllOne() 初始化数据结构的对…...

再析jvm
前言 希望自己每一次学习都有不同的理解 文章目录前言1. jvm的组成取消永久代使用元空间原因2. 运行时数据区3. 堆栈区别队列和栈,队列先进先出,栈先进后出从栈顶弹出4. GC、内存溢出、垃圾回收4.1 如何确定引用是否会被回收4.1.1 Java中的引用类型4.1.…...

社招前端二面面试题总结
代码输出结果 var A {n: 4399}; var B function(){this.n 9999}; var C function(){var n 8888}; B.prototype A; C.prototype A; var b new B(); var c new C(); A.n console.log(b.n); console.log(c.n);输出结果:9999 4400 解析: conso…...

人人能读懂redux原理剖析
一、Redux是什么? 众所周知,Redux最早运用于React框架中,是一个全局状态管理器。Redux解决了在开发过程中数据无限层层传递而引发的一系列问题,因此我们有必要来了解一下Redux到底是如何实现的? 二、Redux的核心思想…...

uniCloud云开发----7、uniapp通过uni-swiper-dot实现轮播图
uniapp通过uni-swiper-dot实现轮播图前言效果图1、官网实现的效果2、需求中使用到的效果图官网提供的效果图源码1、html部分2、js部分3、css部分根据需求调整轮播图前言 uni-swiper-dot.文档 uni-swiper-dot 轮播图指示点 - DCloud 插件市场 本次展示根据需求制作的和官网用到…...

IM即时通讯构建企业协同生态链
在当今互联网信息飞速发展的时代,随着企业对协同办公要求的提高,协同办公的定义提升到了智能化办公的范畴。大多企业都非常重视构建连接用户、员工和合作伙伴的生态平台,利用即时通讯软件解决企业内部的工作沟通、信息传递和知识共享等问题。…...

Python实现构建gan模型, 输入一个矩阵和两个参数值,输出一个矩阵
构建一个GAN模型,使用Python实现,该模型将接受一个矩阵和两个参数值作为输入,并输出另一个矩阵。GAN(生成对抗网络)是一种深度学习模型,由生成器和判别器两部分组成,可以用于生成具有一定规律性的数据,如图像或音频。 # 定义生成器 def make_generator(noise_dim, dat…...
开学准备哪些电容笔?ipad触控笔推荐平价
在现代,数码产品的发展受到高技术的驱动。不管是在工作上,还是在学习上,大的显示屏可以使图像更加清晰。Ipad将成为我们日常生活中不可或缺的一部分,无论现在或将来。如果ipad配上一款方便操作的电容笔,将极大地提高我…...

放下和拿起 解放自己
放下太难,从过去中解放自己 工作这么久了,第一次不拿包上班,真爽 人的成长都是在碰撞和摸索中产生的,通过摸索,知道自己能力的边界和欲望的边界以及身体的边界,这三个决定了 你能做什么 你能享受什么&…...

100%BIM学员的疑惑:不会CAD可以学Revit吗?
在新一轮科技创新和产业变革中,信息化与建筑业的融合发展已成为建筑业发展的方向,将对建筑业发展带来战略性和全局性的影响。 建筑业是传统产业,推动建筑业科技创新,加快推进信息化发展,激发创新活力,培育…...

经常会采坑的javascript原型应试题
一. 前言 原型和原型链在面试中历来备受重视,经常被提及。说难可能也不太难,但要真正完全理解,吃透它,还是要多下功夫的。 下面为大家简单阐述我对原型和原型链的理解,若是觉得有说的不对的地方ÿ…...

完全背包—动态规划
一、背包问题概述 如图,完全背包与01背包的区别只有一点:01背包中每个物品只能取一个而完全背包中每个物品可以取无数个。解决完全背包问题必须首先弄明白01背包,不清楚的可以看我的这篇文章01背包—动态规划。 二、例题 重量价值物品0115物…...

消息队列MQ介绍
消息队列技术是分布式应用间交换信息的一种技术。消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走。通过消息队列,应用程序可独立地执行--它们不需要知道彼此的位置、或在继续执行前不需要等待接收程序接收此消息。 消息中间件概述 消息队列技术是…...

C语言进阶(八)—— 链表
1. 链表基本概念1.1 什么是链表链表是一种常用的数据结构,它通过指针将一些列数据结点,连接成一个数据链。相对于数组,链表具有更好的动态性(非顺序存储)。数据域用来存储数据,指针域用于建立与下一个结点的…...

手工测试用例就是自动化测试脚本——使用ruby 1.9新特性进行自动化脚本的编写
昨天因为要装watir-webdriver的原因将用了快一年的ruby1.8.6升级到了1.9。由于1.9是原生支持unicode编码,所以我们可以使用中文进行自动化脚本的编写工作。 做了简单的封装后,我们可以实现如下的自动化测试代码。请注意,这些代码是可以正确运…...

RockerMQ简介和单节点部署
目录一、RockerMQ简介二、Linux中单节点部署1、准备工作2、下载和解压3、修改初始内存4、启动5、查看进程6、发送接收消息测试7、关闭三、控制台的安装与启动(可视化页面)1、修改配置(1)修改端口号(2)指定RocketMQ的name server地…...

SFP光纤笼子 别称 作用 性能要点 工程要素
Hqst盈盛电子导读:2023年,Hqst盈盛电子于下属五金部开发生产SFP光纤连接器笼子等系列产品,所有产品生产及性标准都将参照连接器产品常用测试标准EIA-364-C等标准,以下为我司常规SFP光纤连接器基本性能要求SFP光纤笼子别称…...

[HarekazeCTF2019]Easy Notes
知识点:session 反序列化,代码审计代码分析 flag.php 中有个 is_admin 函数的判断。 在 lib.php 中有 is_admin 函数,需要 session[admin] 为 true,或者通过文件读取的方式。 在 index.php 中的 include 并不能使用伪协议读取 …...

Java学习-IO流-字符流-FileReader
Java学习-IO流-字符流-FileReader 字符流 字节流 字符集 输入流:默认一次读一个字节,遇到中文时一次读多个字节 输出流:底层把数据按照指定编码方式编码,变成字节写入文件 使用场景:纯文本文件读写 // …...

python攻陷米哈游《元神》数据?详情请看文章。。
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 《原神》是由米哈游自研的一款全新开放世界冒险RPG。 里面拥有许多丰富得角色,让玩家为之着迷~ 今天,我们就来用python探索一下原神游戏角色信息! 标题大家看看就好了哈~(…...