Context数量
- Activity数量 + Service数量 + 1 (1为Application)
Context的继承关系
- Context下有两个子类,ContextWrapper是上下文功能的封装类,而ContextImpl则是上下文功能的实现类;
- ContextWrapper作为Context类的包装类,其内部维护了一个Context类型的成员变量mBase,mBase最终会指向一个ContextImpl对象,ContextWrapper的方法其内部依赖mBase,ContextWrapper是Context类的修饰类(装饰器模式),真正的实现类是 ContextImpl,ContextWrapper 里面的方法调用也是调用 ContextImpl 里面的方法。又有三个直接的子类,ContextThemeWrapper, Service, Application; ContextThemeWrapper是一个带主题的封装类,而它有一个直接子类就是Activity;
- ContextImpl中两个比较重要的变量:
- ActivityThread mMainThread:getApplicationContext,startActivity,getMainLooper
- LoadedApk mPackageInfo: getApplicationContext, getPackageName, getApplicationInfo, getPackageResourcePath
Application Context 创建过程
- 当一个应用程序启动完成后,应用程序就会有一个全局的Application Context
- ActivityThread作为应用程序进程的核心类,它会调用它的内部类ApplicationThread的scheduleLaunchActivity方法来启动Activity,scheduleLaunchActivity方法中向H类发送LAUNCH_ACTIVITY类型的消息,目的是将启动Activity的逻辑放在主线程中的消息队列中,这样启动Activity的逻辑会在主线程中执行。
@Override
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) {
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);
- H类的handleMessage方法对LAUNCH_ACTIVITY类型的消息的处理,通过getPackageInfoNoCheck方法获得LoadedApk类型的对象,并将该对象赋值给ActivityClientRecord 的成员变量packageInfo
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;
//1.通过getPackageInfoNoCheck方法获得LoadedApk类型的对象,并将该对象赋值给ActivityClientRecord 的成员变量packageInfo
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//2. handleLaunchActivity方法中调用了performLaunchActivity
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
- handleLaunchActivity方法中调用了performLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
if (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) {
performPauseActivityIfNeeded(r, reason);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
try {
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
}
...
return activity;
}
- performLaunchActivity中又调用了LoadedApk的makeApplication方法
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {//1
return mApplication;
}
...
try {
...
java.lang.ClassLoader cl = getClassLoader();
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);//2
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);//3
appContext.setOuterContext(app);//4
} catch (Exception e) {
...
}
mActivityThread.mAllApplications.add(app);
mApplication = app;//5
...
return app;
- Instrumentation的newApplication方法如下
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();//1
app.attach(context);
return app;
}
//frameworks/base/core/java/android/app/Application.java
/* package */ final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
//frameworks/base/core/java/android/content/ContextWrapper.java
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
Application Context 获取过程
- 调用getApplicationContext方法来获得Application Context,实现在ContextWrapper中
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
- mBase指的是ContextImpl,我们来查看 ContextImpl的getApplicationContext
@Override
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}
- 由于应用程序这时已经启动,因此LoadedApk不会为null,则会调用LoadedApk的getApplication方法
Application getApplication() {
return mApplication;//在上文LoadedApk的makeApplication方法的注释5处被赋值
Activity的Context创建过程
- 前面 Application Context 创建过程讲到了ActivityThread启动Activity的过程,ActivityThread会调用它的内部类ApplicationThread的scheduleLaunchActivity方法来启动Activity,scheduleLaunchActivity方法中向H类发送LAUNCH_ACTIVITY类型的消息,H类的handleMessage方法对LAUNCH_ACTIVITY类型的消息的处理,调用了handleLaunchActivity方法,handleLaunchActivity方法中又调用了performLaunchActivity,performLaunchActivity中调用了LoadedApk类型的packageInfo的makeApplication方法
- 而performLaunchActivity中还有很多重要的逻辑,如下可以看到还有调用了一个createBaseContextForActivity方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
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);
}
//创建Activity的ContextImpl
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//创建Activity的实例
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);
}
}
try {
// 前面说的调用makeApplication创建Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
//调用了ContextImpl的setOuterContext方法,
//将此前创建的Activity实例赋值给ContextImpl的成员变量mOuterContext,
//这样ContextImpl也可以访问Activity的变量和方法
appContext.setOuterContext(activity);
//将ContextImpl传入activity的attach方法中
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);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
//Instrumentation的callActivityOnCreate方法中会调用Activity的onCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
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;
- createBaseContextForActivity方法
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
...
//调用ContextImpl的createActivityContext方法来创建ContextImpl
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
...
return
- Activity的attach方法调用了ContextThemeWrapper的attachBaseContext方法
;
mFragments.attachHost(null /*parent*/);
//创建PhoneWindow,PhoneWindow在运行中会间接触发很多事件,
//比如点击事件、菜单弹出、屏幕焦点变化等事件,
//这些事件需要转发给与PhoneWindow关联的Actvity,
//转发操作通过Window.Callback接口实现,Actvity实现了这个接口
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);//将当前Activity通过Window的setCallback方法传递给PhoneWindow
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
//给PhoneWindow设置WindowManager
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
//获取WindowManager并赋值给Activity的成员变量mWindowManager,
//这样在Activity中就可以通过getWindowManager方法来获取WindowManager
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
- 上面第一行就调用了ContextThemeWrapper的attachBaseContext方法, 其中直接调用了其父类ContextWrapper的attachBaseContext方法
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
//base指的是一路传递过来的Activity的ContextImpl,
//将它赋值给ContextWrapper的成员变量mBase。
//这样ContextWrapper的功能就可以交由ContextImpl处理,例如
@Override
public Resources.Theme getTheme() {
return mBase.getTheme();
}
//调用ContextWrapper的getTheme方法,其实就是调用的ContextImpl的getTheme方法
Service的Context创建过程
- ActivityThread的内部类ApplicationThread会调用scheduleCreateService方法来启动Service
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);
- 可以看到上面也是通过向H类发送CREATE_SERVICE类型的消息,H类的handleMessage方法中会对CREATE_SERVICE类型的消息进行处理,其中调用了handleCreateService方法
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
private void handleCreateService(CreateServiceData data) {
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//创建service
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}
try {
//创建ContextImpl实例
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
//调用了ContextImpl的setOuterContext方法,
//将service实例赋值给ContextImpl的成员变量mOuterContext,
//这样ContextImpl也可以访问service的变量和方法
context.setOuterContext(service);
//创建(获取)Application实例
Application app = packageInfo.makeApplication(false, mInstrumentation);
//将ContextImpl实例传入service的attach方法
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//调用service的onCreate方法
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
- 上面可以看到其中创建了ContextImpl,并将该ContextImpl传入service的attach方法中
public final void attach(
Context context,
ActivityThread thread, String className, IBinder token,
Application application, Object activityManager) {
//调用了ContextWrapper的attachBaseContext方法
attachBaseContext(context);
mThread = thread; // NOTE:
mClassName = className;
mToken = token;
mApplication = application;
mActivityManager = (IActivityManager)activityManager;
mStartCompatibility = getApplicationInfo().targetSdkVersion
< Build.VERSION_CODES.ECLAIR;
- 可以看到最终也是调用到了ContextWrapper的attachBaseContext方法
几个容易混乱方法
- 再来看一下几个常见的获取context的方法
- getBaseContext是ContextWrapper中的方法,其返回的mBase也就是上面提到的通过attachBaseContext赋值的ContextImpl实例
/**
* @return the base context as set by the constructor or setBaseContext
*/
public Context getBaseContext() {
return
- getApplicationContext是ContextWrapper中的方法,其返回是调用了ContextImpl实例mBase的getApplicationContext方法,最终返回的是一个Application实例
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
//ContextImpl的getApplicationContext方法
@Override
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}
- getApplication是Activity/service中的方法,实在上面的attach方法中赋值给mApplication的Application实例
/** Return the application that owns this activity. */
public final Application getApplication(){
return
- getContext是Fragment中的方法,返回的是通过调用FragmentHostCallback类型的mHost的getContext方法返回其mContext变量
@Nullable
public Context getContext() {
return mHost == null ? null : mHost.getContext();
}
- FragmentHostCallback的getContext方法
@NonNull
Context getContext() {
return mContext;
}
FragmentHostCallback(@NonNull FragmentActivity activity) {
this(activity, activity /*context*/, new Handler(), 0 /*windowAnimations*/);
}
FragmentHostCallback(@Nullable Activity activity, @NonNull Context context,
@NonNull Handler handler, int windowAnimations) {
mActivity = activity;
mContext = Preconditions.checkNotNull(context, "context == null");
mHandler = Preconditions.checkNotNull(handler, "handler == null");
mWindowAnimations = windowAnimations;
}
- 其调用是在
public class FragmentActivity extends ComponentActivity implements
ActivityCompat.OnRequestPermissionsResultCallback,
ActivityCompat.RequestPermissionsRequestCodeValidator {
...
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
...
class HostCallbacks extends FragmentHostCallback<FragmentActivity> implements ViewModelStoreOwner, OnBackPressedDispatcherOwner{
public HostCallbacks() {
super(FragmentActivity.this /*fragmentActivity*/);
}
...
}
...
}
- 上面可以看到其实mContext和mActivity都是通过FragmentActivity.this赋值的
- 打印log看一下
getBaseContext():androidx.appcompat.view.ContextThemeWrapper
getApplicationContext():android.app.Application
getApplication():android.app.Application
this:com.example.viewpagerdemo.MainActivity
Fragment getContext():com.example.viewpagerdemo.MainActivity
正确使用Context
- 一般Context造成的内存泄漏,几乎都是当Context销毁的时候,却因为被引用导致销毁失败
- 优先使用Application的Context,或用弱引用进行封装
- ImageView等都会持有上下文的引用,如果设置了static Drawable对象,就会导致该内存无法释放
activity的startActivity和context的startActivity区别?
- 从Activity中启动新的Activity时可以直接mContext.startActivity(intent)就好,如果从其他Context中启动Activity则必须给intent设置Flag:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ;
mContext.startActivity(intent);
原理:
- 首先startActivity是Context中的抽象方法
public abstract void startActivity(@RequiresPermission
- ContextWrapper中是调用了mBase的,也就是ContextImpl的实现
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent);
}
- ContextImpl的实现,会先检查有没有设置Flag:FLAG_ACTIVITY_NEW_TASK,再调用了mMainThread.getInstrumentation().execStartActivity方法
@Override
public void startActivity(Intent intent) {
warnIfCallingFromSystemProcess();
startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
// Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
// generally not allowed, except if the caller specifies the task id the activity should
// be launched in.
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
&& options != null && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity) null, intent, -1, options);
}
- ContextThemeWrapper中没有实现此方法
- Activity中重写了startActivity方法,最终调用了mInstrumentation.execStartActivity方法,跳过了检查FLAG_ACTIVITY_NEW_TASK
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
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);
}
}
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) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
- 当调用startActivity()方法来启动一个Activity时,默认是将它放入到当前的任务当中。但是,如果在Intent中加入了FLAG_ACTIVITY_NEW_TASK flag的话,情况就会变的复杂起来。首先,系统会去检查这个Activity的affinity是否与当前Task的affinity相同。如果相同的话就会把它放入到当前Task当中,如果不同则会先去检查是否已经有一个名字与该Activity的affinity相同的Task,如果有,这个Task将被调到前台,同时这个Activity将显示在这个Task的顶端;如果没有的话,系统将会尝试为这个Activity创建一个新的Task。需要注意的是,如果一个Activity在manifest文件中声明的启动模式是”singleTask”,那么他被启动的时候,行为模式会和前面提到的指定FLAG_ACTIVITY_NEW_TASK一样。
- 几种启动模式
类型 | 含义 | 说明 |
standard | 标准模式 | 每启动会创建一个新 Activity 实例并置于栈顶。谁启动了这个 Activity,那么这个 Activity 就运行在启动它的那个 Activity 所在的栈中。 |
singleTop | 栈顶模式 | 如果栈顶存在该activity的实例,则复用,不存在新建放入栈顶,例如通知栏点击后需要启动一个活动页 |
singleTask | 栈内复用模式 | 如果栈内存在该 Activity 的实例则进行复用(会将该实例上边的 Activity 全部出栈,将该实例置于栈顶),如果不存在则创建。例如主 Activity 的启动模式改为栈内复用,再跳转到另一个二级页,按home键回到桌面,再切回,二级页会被销毁。 |
singleInstance | 单实例模式 | 这种模式启动的activity只能单独的位于一个任务栈中,在整个应用中仅存在单个实例,APP首页/主页/呼叫来电界面 |
singleInstancePerTask | 栈内根单例 | 每个任务里存在于根部的单个实例,多窗口并排功能的时候可以使用,例如:Chrome 浏览器的多窗口 |
- 启动模式优先级: Intent标记 > AndroidManifest文件
Android12 中 Activity 生命周期的变化
- Android 12 以前,当我们处于 Root Activity 时,点击返回键时,应用返回桌面, Activity 执行 onDestroy,程序结束。 Android 12 起同样场景下 Activity 只会 onStop,不再执行 onDestroy。其他 Activity 点击返回键后行为不变,依然会 onDestroy
- ViewModel 的销毁在 onDestroy 中,这样改动后 ViewModel 中的状态可以保存,再次启动后可以直接使用。对于使用者来说直接感受就是冷启动变为了热启动,启动速度更快。
Android12 之前的设备:
// 初次启动
D/SampleActivity: ON_CREATE
D/SampleActivity: ON_START
D/SampleActivity: ON_RESUME
// 返回桌面
D/SampleActivity: ON_PAUSE
D/SampleActivity: ON_STOP
D/SampleActivity: ON_DESTROY
// 再次启动
D/SampleActivity: ON_CREATE
D/SampleActivity: ON_START
D/SampleActivity: ON_RESUME
Android12 之后的设备:
// 初次启动
D/SampleActivity: ON_CREATE
D/SampleActivity: ON_START
D/SampleActivity: ON_RESUME
// 返回桌面
D/SampleActivity: ON_PAUSE
D/SampleActivity: ON_STOP
// 再次启动
D/SampleActivity: ON_START
D/SampleActivity: ON_RESUME