Android startActivity流程

2023-11-05 05:30

本文主要是介绍Android startActivity流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.常规调用

startActivity(new Intent(this,MainActivity.class));

进入Activity的startActivity方法

    /*** Same as {@link #startActivity(Intent, Bundle)} with no options* specified.** @param intent The intent to start.** @throws android.content.ActivityNotFoundException** @see #startActivity(Intent, Bundle)* @see #startActivityForResult*/@Overridepublic void startActivity(Intent intent) {this.startActivity(intent, null);}

 进入Activity的startActivityForResult方法

    /*** Launch a new activity.  You will not receive any information about when* the activity exits.  This implementation overrides the base version,* providing information about* the activity performing the launch.  Because of this additional* information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not* required; if not specified, the new activity will be added to the* task of the caller.** <p>This method throws {@link android.content.ActivityNotFoundException}* if there was no Activity found to run the given Intent.** @param intent The intent to start.* @param options Additional options for how the Activity should be started.* See {@link android.content.Context#startActivity(Intent, Bundle)}* Context.startActivity(Intent, Bundle)} for more details.** @throws android.content.ActivityNotFoundException** @see #startActivity(Intent)* @see #startActivityForResult*/@Overridepublic void startActivity(Intent intent, @Nullable Bundle options) {getAutofillClientController().onStartActivity(intent, mIntent);if (options != null) {startActivityForResult(intent, -1, options);} else {// Note we want to go through this call for compatibility with// applications that may have overridden the method.startActivityForResult(intent, -1);}}
    /*** Same as calling {@link #startActivityForResult(Intent, int, Bundle)}* with no options.** @param intent The intent to start.* @param requestCode If >= 0, this code will be returned in*                    onActivityResult() when the activity exits.** @throws android.content.ActivityNotFoundException** @see #startActivity*/public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {startActivityForResult(intent, requestCode, null);}
    /*** Launch an activity for which you would like a result when it finished.* When this activity exits, your* onActivityResult() method will be called with the given requestCode.* Using a negative requestCode is the same as calling* {@link #startActivity} (the activity is not launched as a sub-activity).** <p>Note that this method should only be used with Intent protocols* that are defined to return a result.  In other protocols (such as* {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may* not get the result when you expect.  For example, if the activity you* are launching uses {@link Intent#FLAG_ACTIVITY_NEW_TASK}, it will not* run in your task and thus you will immediately receive a cancel result.** <p>As a special case, if you call startActivityForResult() with a requestCode* >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your* activity, then your window will not be displayed until a result is* returned back from the started activity.  This is to avoid visible* flickering when redirecting to another activity.** <p>This method throws {@link android.content.ActivityNotFoundException}* if there was no Activity found to run the given Intent.** @param intent The intent to start.* @param requestCode If >= 0, this code will be returned in*                    onActivityResult() when the activity exits.* @param options Additional options for how the Activity should be started.* See {@link android.content.Context#startActivity(Intent, Bundle)}* Context.startActivity(Intent, Bundle)} for more details.** @throws android.content.ActivityNotFoundException** @see #startActivity*/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());}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;}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);}}}

如果父activity不存在就调用

mInstrumentation.execStartActivity

如果父activity存在就调用

mParent.startActivityFromChild

mInstrumentation.execStartActivity会调用ATMS的

ActivityTaskManager.getService().startActivity
    /*** Execute a startActivity call made by the application.  The default * implementation takes care of updating any active {@link ActivityMonitor}* objects and dispatches this call to the system activity manager; you can* override this to watch for the application to start an activity, and * modify what happens when it does. ** <p>This method returns an {@link ActivityResult} object, which you can * use when intercepting application calls to avoid performing the start * activity action but still return the result the application is * expecting.  To do this, override this method to catch the call to start * activity so that it returns a new ActivityResult containing the results * you would like the application to see, and don't call up to the super * class.  Note that an application is only expecting a result if * <var>requestCode</var> is &gt;= 0.** <p>This method throws {@link android.content.ActivityNotFoundException}* if there was no Activity found to run the given Intent.** @param who The Context from which the activity is being started.* @param contextThread The main thread of the Context from which the activity*                      is being started.* @param token Internal token identifying to the system who is starting *              the activity; may be null.* @param target Which activity is performing the start (and thus receiving *               any result); may be null if this call is not being made*               from an activity.* @param intent The actual Intent to start.* @param requestCode Identifier for this request's result; less than zero *                    if the caller is not expecting a result.* @param options Addition options.** @return To force the return of a particular result, return an *         ActivityResult object containing the desired data; otherwise*         return null.  The default implementation always returns null.** @throws android.content.ActivityNotFoundException** @see Activity#startActivity(Intent)* @see Activity#startActivityForResult(Intent, int)** {@hide}*/@UnsupportedAppUsagepublic 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);ActivityResult result = null;if (am.ignoreMatchingSpecificIntents()) {if (options == null) {options = ActivityOptions.makeBasic().toBundle();}result = am.onStartActivity(who, intent, options);}if (result != null) {am.mHits++;return result;} else if (am.match(who, null, intent)) {am.mHits++;if (am.isBlocking()) {return requestCode >= 0 ? am.getResult() : null;}break;}}}}try {intent.migrateExtraStreamToClipData(who);intent.prepareToLeaveProcess(who);int result = ActivityTaskManager.getService().startActivity(whoThread,who.getOpPackageName(), who.getAttributionTag(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()), token,target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;}

mParent.startActivityFromChild内部调用的也是mInstrumentation.execStartActivity

    /*** This is called when a child activity of this one calls its* {@link #startActivity} or {@link #startActivityForResult} method.** <p>This method throws {@link android.content.ActivityNotFoundException}* if there was no Activity found to run the given Intent.** @param child The activity making the call.* @param intent The intent to start.* @param requestCode Reply request code.  < 0 if reply is not requested.* @param options Additional options for how the Activity should be started.* See {@link android.content.Context#startActivity(Intent, Bundle)}* Context.startActivity(Intent, Bundle)} for more details.** @throws android.content.ActivityNotFoundException** @see #startActivity* @see #startActivityForResult* @deprecated Use {@code androidx.fragment.app.FragmentActivity#startActivityFromFragment(* androidx.fragment.app.Fragment,Intent,int,Bundle)}*/@Deprecatedpublic void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,int requestCode, @Nullable Bundle options) {options = transferSpringboardActivityOptions(options);Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, child,intent, requestCode, options);if (ar != null) {mMainThread.sendActivityResult(mToken, child.mEmbeddedID, requestCode,ar.getResultCode(), ar.getResultData());}cancelInputsAndStartExitTransition(options);}

framework/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

startActivity调用startActivityAsUser

@Overridepublic final int startActivity(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,Bundle bOptions) {return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());}

 startActivityAsUser

@Overridepublic int startActivityAsUser(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,Bundle bOptions, int userId) {return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,true /*validateIncomingUser*/);}
private int startActivityAsUser(IApplicationThread caller, String callingPackage,@Nullable String callingFeatureId, Intent intent, String resolvedType,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {assertPackageMatchesCallingUid(callingPackage);enforceNotIsolatedCaller("startActivityAsUser");userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");// TODO: Switch to user app stacks here.return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setUserId(userId).execute();}

获取:getActivityStartController().obtainStarter

ActivityStartController getActivityStartController() {return mActivityStartController;}
ActivityStarter obtainStarter(Intent intent, String reason) {return mFactory.obtain().setIntent(intent).setReason(reason);}
/*** Resolve necessary information according the request parameters provided earlier, and execute* the request which begin the journey of starting an activity.* @return The starter result.*/int execute() {try {// Refuse possible leaked file descriptorsif (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) {throw new IllegalArgumentException("File descriptors passed in Intent");}final LaunchingState launchingState;synchronized (mService.mGlobalLock) {final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);final int callingUid = mRequest.realCallingUid == Request.DEFAULT_REAL_CALLING_UID?  Binder.getCallingUid() : mRequest.realCallingUid;launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mRequest.intent, caller, callingUid);}// If the caller hasn't already resolved the activity, we're willing// to do so here. If the caller is already holding the WM lock here,// and we need to check dynamic Uri permissions, then we're forced// to assume those permissions are denied to avoid deadlocking.if (mRequest.activityInfo == null) {mRequest.resolveActivity(mSupervisor);}// Add checkpoint for this shutdown or reboot attempt, so we can record the original// intent action and package name.if (mRequest.intent != null) {String intentAction = mRequest.intent.getAction();String callingPackage = mRequest.callingPackage;if (intentAction != null && callingPackage != null&& (Intent.ACTION_REQUEST_SHUTDOWN.equals(intentAction)|| Intent.ACTION_SHUTDOWN.equals(intentAction)|| Intent.ACTION_REBOOT.equals(intentAction))) {ShutdownCheckPoints.recordCheckPoint(intentAction, callingPackage, null);}}int res;synchronized (mService.mGlobalLock) {final boolean globalConfigWillChange = mRequest.globalConfig != null&& mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();if (rootTask != null) {rootTask.mConfigWillChange = globalConfigWillChange;}ProtoLog.v(WM_DEBUG_CONFIGURATION, "Starting activity when config "+ "will change = %b", globalConfigWillChange);final long origId = Binder.clearCallingIdentity();res = resolveToHeavyWeightSwitcherIfNeeded();if (res != START_SUCCESS) {return res;}res = executeRequest(mRequest);Binder.restoreCallingIdentity(origId);if (globalConfigWillChange) {// If the caller also wants to switch to a new configuration, do so now.// This allows a clean switch, as we are waiting for the current activity// to pause (so we will not destroy it), and have not yet started the// next activity.mService.mAmInternal.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,"updateConfiguration()");if (rootTask != null) {rootTask.mConfigWillChange = false;}ProtoLog.v(WM_DEBUG_CONFIGURATION,"Updating to new configuration after starting activity.");mService.updateConfigurationLocked(mRequest.globalConfig, null, false);}// The original options may have additional info about metrics. The mOptions is not// used here because it may be cleared in setTargetRootTaskIfNeeded.final ActivityOptions originalOptions = mRequest.activityOptions != null? mRequest.activityOptions.getOriginalOptions() : null;// If the new record is the one that started, a new activity has created.final boolean newActivityCreated = mStartActivity == mLastStartActivityRecord;// Notify ActivityMetricsLogger that the activity has launched.// ActivityMetricsLogger will then wait for the windows to be drawn and populate// WaitResult.mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,newActivityCreated, mLastStartActivityRecord, originalOptions);if (mRequest.waitResult != null) {mRequest.waitResult.result = res;res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,launchingState);}return getExternalResult(res);}} finally {onExecutionComplete();}}

Android | Activity 启动流程分析 - 掘金 (juejin.cn)

这篇关于Android startActivity流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/347718

相关文章

使用MongoDB进行数据存储的操作流程

《使用MongoDB进行数据存储的操作流程》在现代应用开发中,数据存储是一个至关重要的部分,随着数据量的增大和复杂性的增加,传统的关系型数据库有时难以应对高并发和大数据量的处理需求,MongoDB作为... 目录什么是MongoDB?MongoDB的优势使用MongoDB进行数据存储1. 安装MongoDB

Python实现NLP的完整流程介绍

《Python实现NLP的完整流程介绍》这篇文章主要为大家详细介绍了Python实现NLP的完整流程,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 编程安装和导入必要的库2. 文本数据准备3. 文本预处理3.1 小写化3.2 分词(Tokenizatio

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

SpringBoot使用minio进行文件管理的流程步骤

《SpringBoot使用minio进行文件管理的流程步骤》MinIO是一个高性能的对象存储系统,兼容AmazonS3API,该软件设计用于处理非结构化数据,如图片、视频、日志文件以及备份数据等,本文... 目录一、拉取minio镜像二、创建配置文件和上传文件的目录三、启动容器四、浏览器登录 minio五、

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

Nginx、Tomcat等项目部署问题以及解决流程

《Nginx、Tomcat等项目部署问题以及解决流程》本文总结了项目部署中常见的four类问题及其解决方法:Nginx未按预期显示结果、端口未开启、日志分析的重要性以及开发环境与生产环境运行结果不一致... 目录前言1. Nginx部署后未按预期显示结果1.1 查看Nginx的启动情况1.2 解决启动失败的

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影