All of my articles are collected in this article, and will be updated in time: Knowledge is long, the road of the walker will end in no words (My Programming Road)
Zero, preface,
1. Knowledge points of this article
[1]. Test and analysis of the life cycle on the Elasticity of activities [2]. Data transfer between activities [3]. Detailed analysis of four [startup modes] for activities [4]Copy the code
2. The Activity overview
Class name :Activity Parent class :ContextThemeWrapper modifier :public Package name: Android.app Number of dependent classes :115 Number of internal classes/interfaces: 5 Number of source lines: 7754 Number of source lines (except comments):3197 Number of properties: 20 Number of methods :282 Public method number :245Copy the code
I. Life cycle testing:
1. Open and close
1.1. Opening LifeCycleActivity:
2019-01-19 14:06:10.614: LifeCycleActivity--onCreate: 2019-01-19 14:06:10.617: LifeCycleActivity--onStart: 2019-01-19 14:06:10.614: LifeCycleActivity--onStart: The 2019-01-19 14:06:10. 634: LifeCycleActivity -- onResume:Copy the code
1.2. The Back key closes LifeCycleActivity:
2019-01-19 14:08:53.247: LifeCycleActivity--onStop: 2019-01-19 14:08:52.675: LifeCycleActivity--onStop: 2019-01-19 14:08:53.247: LifeCycleActivity--onStop: The 2019-01-19 14:08:53. 249: LifeCycleActivity -- onDestroy:Copy the code
2. Jump the life cycle of two normal activities
2.1. Open CommonActivity in LifeCycleActivity:
2019-01-19 14:15:57.454: LifeCycleActivity--onPause: 2019-01-19 14:15:57.495: CommonActivity--onCreate: 2019-01-19 14:15:57.501: CommonActivity--onResume: 2019-01-19 14:15:57.501: CommonActivity--onResume: 2019-01-19 14:15:57.501: CommonActivity--onResume: The 2019-01-19 14:15:58. 256: LifeCycleActivity -- onStop:Copy the code
2.2.CommonActivity Go back to LifeCycleActivity:
2019-01-19 14:19:09.511: CommonActivity--onPause: 2019-01-19 14:19:09.527: LifeCycleActivity--onRestart: 2019-01-19 14:19:09.511: CommonActivity--onPause: 2019-01-19 14:19:09.527: LifeCycleActivity--onRestart: 2019-01-19 14:19:09.528: LifeCycleActivity--onStart: 2019-01-19 14:19:09.529: LifeCycleActivity--onResume: 2019-01-19 14:19:09.529: LifeCycleActivity--onResume: 2019-01-19 14:19:09.963: CommonActivity--onDestroy: 2019-01-19 14:19:09.963: CommonActivity--onDestroy: 2019-01-19 14:19:09.963: CommonActivity--onDestroy:Copy the code
3. Jump the life cycle of the two activities in the dialog box Activity
3.1. Start DialogActivity in LifeCycleActivity:
2019-01-19 14:43:32.842: LifeCycleActivity--onPause: 2019-01-19 14:43:32.908: DialogActivity--onCreate: 2019-01-19 14:43:32.842: LifeCycleActivity--onPause: 2019-01-19 14:43:32.908: DialogActivity--onCreate: 2019-01-19 14:43:32.910: DialogActivity--onStart: 2019-01-19 14:43:32.912: DialogActivity--onResume:Copy the code
3.2.DialogActivity Return key to LifeCycleActivity:
2019-01-19 14:44:45.771: DialogActivity--onPause: 2019-01-19 14:44:45.812: LifeCycleActivity--onResume: 2019-01-19 14:44:45.874: DialogActivity--onDestroy: 2019-01-19 14:44:45.874: DialogActivity--onDestroy: 2019-01-19 14:44:45.874: DialogActivity--onDestroy:Copy the code
4.LifeCycleActivity Rotates the screen (equivalent to turning it off and on) :
2019-01-19 14:46:28.619: LifeCycleActivity--onPause: 2019-01-19 14:46:28.639: LifeCycleActivity--onStop: 2019-01-19 14:46:28.619: LifeCycleActivity--onStop: 2019-01-19 14:46:28.639: LifeCycleActivity--onDestroy: 2019-01-19 14:46:28.743: LifeCycleActivity--onCreate: 2019-01-19 14:46:28.744: LifeCycleActivity--onStart: 2019-01-19 14:46:28.751: LifeCycleActivity--onResume: 2019-01-19 14:46:28.751: LifeCycleActivity--onResume:Copy the code
Activity Lifecycle Test Overview (best viewed on computer)
5. Save data:
Before onStop, It’s going to call onSaveInstanceState and there’s a Bundle object that you can use to store the data and that’s the Bundle object that’s in onCreate, savedInstanceState, and you’re going to use onSaveInstanceState when you rotate the screen
override
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.ac_lifecycle)
title = "LifeCycleActivity"
if(savedInstanceState ! = null) { title = savedInstanceState.getString("name")
}
}
override fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState)
Log.e(TAG, "LifeCycleActivity--onSaveInstanceState: ")}Copy the code
Ii. Interpretation of life cycle methods:
The so-called life cycle, is from birth to death there is a clear callback function function in different states by the Android framework layer callback, simplify the development process. Let developers only focus on the Activity state and build logic based on the state without having to dig into the underlying implementation. There are seven main lifecycle callbacks for an Activity. The following is a classic Activity lifecycle diagram:
Create: onCreate () : | - can be used for initialization, such assetStart ContentView, initialization, data interface resources: onStart () : | - visible but cannot interact recovery: onResume () : | - to restore the animation, music, video and other suspended: onPause () : | - can be used as data storage, stop animation, music, video, etc: onStop () : | - at this point the Activity is not visible, can do heavyweight circumstances do recycling work, to avoid being Killed destroy: onDestroy () : | - recycling, resource release: onRestart () : | - can do something to return to workCopy the code
3. Data transfer between activities
1. Entity class:Person
Person */ class Person(var name: String?, var age: Int) : Serializable { override fun toString(): String {return "Person{" +
"name='" + name + '\''.toString() + ", age=" + age + '}'.toString() } }Copy the code
2. Pass the basic data type, Serializable object, and Parcelable object
Note that the Bundle cannot pass large data
-- -- -- - > [FromActivity click] -- -- -- -- -- -- -- -- -- -- - id_btn_for_result. SetOnClickListener {val intent = intent (this, ToActivity::class.java) val bundle = Bundle() bundle.putSerializable("person", Person("form", 24))
val bitmap = BitmapFactory.decodeResource(resources, R.mipmap.wall_a)
bundle.putParcelable("bitmap", bitmap)
intent.putExtra("from", bundle)
intent.putExtra("title"."Zhang Feng Jie Te Li") startActivity(intent) ---->[ToActivity receive use]----------- val title = Intent.getStringextra ("title")
if(title ! = null) { this.title = title } val extra = intent.getBundleExtra("from")
if(extra ! = null) { val from = extra.get("person") as Person
val icon = extra.get("bitmap") as Bitmap
id_tv_result.text = from.toString()
id_iv_icon.setImageBitmap(icon)
}
Copy the code
3.FromActivity Starts ToActivity with startActivityForResult and returns the value
---->[FromActivity]----------- Companion Object {private const val DATA_CODE = 0x0001 id_btn_for_result.setOnClickListener { val intent = Intent(this, ToActivity::class.java) startActivityForResult(intent, } requestCode: Int, resultCode: Int, data: resultCode: Int, data: resultCode: Int Intent) { when (requestCode) { DATA_CODE ->if (resultCode == Activity.RESULT_OK) {
val dataFormTarget = data.getStringExtra("data")
val personData = data.getBundleExtra("To")
val person = personData.get("person") as Person
id_tv_result_back.text = ("dataFormTarget:" + dataFormTarget
+ "\nperson:"+ person. The toString ())}}} - > [ToActivity transmit data to the FromActivity] -- -- -- -- -- -- -- -- -- -- - private funbackWithData() {
val jt = Person("Jet", 24)
val intent = Intent()
intent.putExtra("data"."I'm the data of ToActivity.")
val bundle = Bundle()
bundle.putSerializable("person", jt)
intent.putExtra("To", bundle)
setResult(Activity.RESULT_OK, intent)
}
Copy the code
4. Open the gallery and set pictures
Id_iv_icon.setonclicklistener {val Intent = Intent(Intent.action_pick) Intent.type ="image/*"; Override Fun onActivityResult(requestCode: Int, resultCode: Int, data: data) Intent?) { super.onActivityResult(requestCode, resultCode, data)if(requestCode == 0 && resultCode == Activity.result_OK) {val selectedImage = data? .data ? :returnVal filePathColumn = arrayOf MediaStore. Images. Media. (DATA) val cursor = contentResolver. The query (/ / access to choose picture view of the DATA selectedImage, filePathColumn, null, null, Null) cursor.moveToFirst() // Get the path of the selected column from the data view val columnIndex = cursor.getColumnIndex(filePathColumn[0]) val picturePath = cursor.getString(columnIndex) cursor.close() id_iv_icon.setImageBitmap(BitmapFactory.decodeFile(picturePath)) } }Copy the code
Three, the Activity of the four startup modes
Activity task stack: Sequence of activities for an Activity
SingleTop: indicates the top overuse stack. SingleTask: indicates the unique object stack. SingleInstance: indicates the singleInstance stackCopy the code
1. Standard:Standard stack
When you start an Activity, create a new instance of that Activity. Push on top of the stack test: Activity1 and 2 are both standard
E/TASK_ID: Activity1 Task ID is 89 E/TASK_ID: Activity2 Task ID is 89 E/TASK_ID: Activity2 Task ID is 89 E/TASK_ID: Activity2 Task ID is 89 E/TASK_ID: Activity2 Task ID is 89 E/TASK_ID: Activity1 Task ID is 89 E/TASK_ID: Activity2 Task ID is 89 E/TASK_ID: Activity2 Task ID is 89 Activity2 Destruct E/TASK_ID: Activity1 destruct E/TASK_ID: Activity2 destruct E/TASK_ID: Activity2 destruct E/TASK_ID: Activity1 destructCopy the code
2: singleTop mode:Top reuse stack
If the Activity is already at the top of the stack when the Activity is started, use it directly without creating an instance test: Activity1 is standard, and Activity2 is singleTop
E/TASK_ID: Activity1 Task ID is 82 E/TASK_ID: Activity2 Task ID is 82 E/TASK_ID: Activity2 Task ID is 82 E/TASK_ID: Activity2 Task ID is 82 E/TASK_ID: Activity1 Task ID is 82 E/TASK_ID: Activity2 Task ID is 82 Return E/TASK_ID: Activity2 Destroy E/TASK_ID: Activity1 Destroy E/TASK_ID: Activity2 Destroy E/TASK_ID: Activity1 destroyCopy the code
3: singleTask mode:Object unique stack
There are no identical instances across the stack, and the Activity between two identical instances will be killed. Test: Activity1 for Standard, Activity2 for singleTask
E/TASK_ID: Activity1 Task ID is 94 E/TASK_ID: Activity2 Task ID is 94 E/TASK_ID: Activity2 Task ID is 94 E/TASK_ID: Activity2 Task ID is 94 Activity1 Task ID is 94 E/TASK_ID: Activity1 Destroy E/TASK_ID: Activity2 Destroy E/TASK_ID: Activity1 destroy E/TASK_ID: Activity1 destroyCopy the code
4: singleInstanceSingle instance stack
Enable a new activity stack to manage this activity (enough, enough willful) test: Activity1 for Standard, Activity2 singleInstance
E/TASK_ID: Activity1 Task ID is 115 E/TASK_ID: Activity2 Task ID is 116 E/TASK_ID: Activity2 Task ID is 116 E/TASK_ID: Activity1 Task ID is 115 E/TASK_ID: Activity2 Destroy E/TASK_ID: Activity1 destroy E/TASK_ID: Activity1 destroyCopy the code
Note: The onCreate method is not called when the singleTask and singleTop modes are not started for the first time! But the onNewIntent method is takenCopy the code
4. Jump animation of the Activity
Here are just four simple panning animations that need more cool effects for the same reason. For more information on animation, see The Android Animator Family Guide
The default | Modify the |
---|---|
1. Code to achieve Activity jump
/ * * * the author: packer jet fierce < br > < br > * time: 2019/1/20/020: instructed < br > < br > * E-mail: 1981462002 @qq.com < br > < br > * note: */ class RedActivity:AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val view = View(this)
view.setBackgroundColor(Color.RED)
title = "RedActivity"
view.setOnClickListener { v ->
startActivity(Intent(this, BlueActivity::class.java))
overridePendingTransition(R.anim.open_enter, R.anim.open_exit);
}
setContentView(view)
}
override fun onBackPressed() { super.onBackPressed() overridePendingTransition(R.anim.open_enter, R.anim.open_exit); * * *}} / author: packer jet fierce < br > < br > * time: 2019/1/20/020: instructed < br > < br > * E-mail: 1981462002 @qq.com < br > < br > * note: Green Activity */ class BlueActivity:AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val view = View(this)
view.setBackgroundColor(Color.BLUE)
title = "BlueActivity"
view.setOnClickListener { v ->
startActivity(Intent(this, RedActivity::class.java))
overridePendingTransition(R.anim.close_enter, R.anim.close_exit)
}
setContentView(view)
}
override fun onBackPressed{super. OnBackPressed () () / / right move - right out overridePendingTransition (state Richard armitage nim. Close_enter, state Richard armitage nim. Close_exit)}}Copy the code
2. Jump animation
---->[open_enter.xml]---------------------- <? xml version="1.0" encoding="utf-8"? > <set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"> <! <translate android:duration="500"
android:fromXDelta="100%p"
android:toXDelta="0%p"/>
</set> ---->[open_exit.xml]---------------------- <? xml version="1.0" encoding="utf-8"? > <set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"> <! <translate android:duration="500"
android:fromXDelta="0%p"
android:toXDelta="-100%p"/>
</set>
---->[close_enter.xml----------------------
<?xml version="1.0" encoding="utf-8"? > <set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"> <! <translate android:duration="500"
android:fromXDelta="-100%p"
android:toXDelta="0%p"/>
</set> ---->[close_exit.xml]---------------------- <? xml version="1.0" encoding="utf-8"? > <set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"> <! <translate android:duration="500"
android:fromXDelta="0%p"
android:toXDelta="100%p"/>
</set>
Copy the code
That will do
3.In addition
You can also configure the style of the animation
It’s easier to use than in code
<! < span style = "box-sizing: border-box! Important; word-wrap: break-word! Important"TranAnim_Activity" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/open_enter</item>
<item name="android:activityOpenExitAnimation">@anim/open_exit</item>
<item name="android:activityCloseEnterAnimation">@anim/close_enter</item>
<item name="android:activityCloseExitAnimation">@anim/close_exit</item> </style> <! -- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <! -- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowAnimationStyle">@style/TranAnim_Activity</item>
</style>
Copy the code
V. Start source analysis on the Elasticity
I want to summarize the Activity launch process (), so let’s start with the Activity lifecycle. The main start process in this article is the H of the ActivityThread, which is called handleMessage after receiving the message. How the message is delivered will be described in the cross process communication section
1. Who’s behind it?
If you look at the source code, you can see that Context is just an abstract class that defines a lot of abstract methods and ContextWrapper as the implementation class throws all the work away to a Context member variable called ContextThemeWrapper in mBase a hundred lines of code, not behind the scenes, Now we only have mBase on the tableCopy the code
2. How is an Activity created?
No one should go to new Activity(). How does the Framework layer create an instance of an Activity?
---->[ActivityThread]-------
final H mH = new H();
---->[ActivityThread$H#handleMessage]-------
public void handleMessage(Message msg) {
switch (msg.what) {
caseLAUNCH_ACTIVITY: {// Start the Activity trace.traceBegin (trace.trace_tag_activity_manager,"activityStart"); Final ActivityClientRecord r = (ActivityClientRecord) MSG. Obj; // final ActivityClientRecord r = (ActivityClientRecord) MSG. / / get package information by r r.p ackageInfo = getPackageInfoNoCheck (state Richard armitage ctivityInfo. ApplicationInfo, r.com patInfo); // Start the core method handleLaunchActivity(r, null,"LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
---->[ActivityThread#handleLaunchActivity]-------private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String Reason) {// Return the Activity object here. 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); / / a little... } ---->[ActivityThread#performLaunchActivity]-------Private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {// ComponentName component = r.intent.getComponent(); Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); / / here is mInstrumentation create Activity Activity. = mInstrumentation newActivity (cl, component getClassName (), r.i ntent); StrictMode.incrementExpectedActivityCount(activity.getClass()); / / a little...return activity;
}
---->[Instrumentation#newActivity]-------public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException {// Generate an Activity instance through the class loaderreturn (Activity)cl.loadClass(className).newInstance();
}
Copy the code
Application instantiation and onCreate() method call
Implement the performLaunchActivity method that moves to the Activity you just created
---->[ActivityThread#performLaunchActivity]-------Private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {// ComponentName component = r.intent.getComponent(); Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); / / a little... Try {// After creating the Activity, create the Application using the makeApplication // of the ActivityClientRecord's packageInfo object. PackageInfo is a LoadedApk class object Application app = r.p ackageInfo. MakeApplication (false, mInstrumentation); / / a little... } ---->[LoadedApk#makeApplication]-------
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if(mApplication ! = null) {returnmApplication; } Application app = null; / / a little... try { java.lang.ClassLoader cl = getClassLoader(); / / a little... / / here played ContextImpl ContextImpl appContext = ContextImpl. CreateAppContext (mActivityThread, this); / / here through mInstrumentation newApplication method to create the Application object app. = mActivityThread mInstrumentation. NewApplication (cl, appClass, appContext); / / will create Application Settings to the appContext appContext. SetOuterContext (app); } / / slightly... / / mActivityThread will join the mActivityThread mAllApplications list. The current app mAllApplications. Add (app); mApplication = app;if(instrumentation ! = null) {try {/ / when the calling application OnCreate method instrumentation. CallApplicationOnCreate (app); } catch (Exception e) {if(! instrumentation.onException(app, e)) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); throw new RuntimeException("Unable to create application " + app.getClass().getName()
+ ":"+ e.toString(), e); }}}return app;
}
---->[Instrumentation#newApplication]-------public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {// Also obtains the Application instance by reflectionreturn newApplication(cl.loadClass(className), context);
}
---->[Instrumentation#callApplicationOnCreate]-------public void callApplicationOnCreate(Application app) { app.onCreate(); // Call onCreate onCreate directlyCopy the code
4. The Activity Context is created and the onCreate() method is called
---->[ActivityThread#performLaunchActivity]-------
if(activity ! = null) { Context appContext = createBaseContextForActivity(r, activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration);if(r.overrideConfig ! = null) { config.updateFrom(r.overrideConfig); }if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if(r.mPendingRemoveWindow ! = null && r.mPreserveWindow) { window = r.mPendingRemoveWindow; r.mPendingRemoveWindow = null; r.mPendingRemoveWindowManager = null; Attach (appContext, this, getInstrumentation(), R.token, R.indent, app, R.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window);if(customIntent ! = null) { activity.mIntent = customIntent; } r.lastNonConfigurationInstances = null; activity.mStartedActivity =false;
int theme = r.activityInfo.getThemeResource();
if(theme ! = 0) { activity.setTheme(theme); } activity.mCalled =false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
---->[ActivityThread#createBaseContextForActivity]-------Private Context createBaseContextForActivity (ActivityClientRecord r, final Activity Activity) {/ / slightly... // appContext is a ContextImpl class object, The Activity of the Context behind the ContextImpl appContext = ContextImpl. CreateActivityContext (this, r.p ackageInfo, r.t oken, displayId, r.overrideConfig); appContext.setOuterContext(activity); Context baseContext = appContext; final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); // For debugging purposes,if the activity's package name contains the value of // the "debug.use-second-display" system property as a substring, then show // its content on a secondary display if there is one. String pkgName = SystemProperties.get("debug.second-display.pkg"); if (pkgName ! = null && ! pkgName.isEmpty() && r.packageInfo.mPackageName.contains(pkgName)) { for (int id : dm.getDisplayIds()) { if (id ! = Display.DEFAULT_DISPLAY) { Display display = dm.getCompatibleDisplay(id, appContext.getDisplayAdjustments(id)); baseContext = appContext.createDisplayContext(display); break; } } } return baseContext; } ---->[ContextImpl#createActivityContext]------- static ContextImpl createActivityContext(ActivityThread mainThread, LoadedApk packageInfo, IBinder activityToken, int displayId, Configuration overrideConfiguration) { if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); return new ContextImpl(null, mainThread, packageInfo, activityToken, null, 0, null, overrideConfiguration, displayId); } ---->[Instrumentation#callActivityOnCreate]------- public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) { prePerformCreate(activity); activity.performCreate(icicle, persistentState); postPerformCreate(activity); } ---->[Activity#performCreate]------- final void performCreate(Bundle icicle, PersistableBundle persistentState) { restoreHasCurrentPermissionRequest(icicle); onCreate(icicle, persistentState); mActivityTransitionState.readState(icicle); performCreateCommon(); } ---->[Activity#attach]----------------- final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window) { attachBaseContext(context); mFragments.attachHost(null /*parent*/); PhoneWindow mWindow = new PhoneWindow(this, Window); PhoneWindow mWindow = new PhoneWindow(this, Window); mWindow.setWindowControllerCallback(this); mWindow.setCallback(this); 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()); } } 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()); } mWindowManager = mWindow.getWindowManager(); mCurrentConfig = config; }Copy the code
5. Layout loading of the Activity
We’re familiar with setContentView. How does the Activity source load
---->[Activity#setContentView]-----------------
public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); } // Visible through Windowset// Attach method to know that the window object is a PhoneWindow class ---->[PhoneWindow#setContentView]-----------------
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
if(mContentParent == null) { installDecor(); // Initialize the DecorView}else if(! hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); }if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
view.setLayoutParams(params);
final Scene newScene = new Scene(mContentParent, view);
transitionTo(newScene);
} else {
mContentParent.addView(view, params);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if(cb ! = null && ! isDestroyed()) { cb.onContentChanged(); } } ---->[PhoneWindow#installDecor]-----------------
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if(! mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures ! = 0) { mDecor.postOnAnimation(mInvalidatePanelMenuRunnable); }}ifMContentParent == null) {// Create mContentParent = generateLayout(mDecor); // The decor of the mDecor is not... ---->[PhoneWindow#generateDecor]-----------------
protected DecorView generateDecor() {
returnnew DecorView(getContext(), -1); } > < span style = "box-sizing: border-box; color: RGB (74, 74, 74); DecorView Extends FrameLayout Implements RootViewSurfaceTaker Private Final Class DecorView Extends FrameLayout Implements RootViewSurfaceTakerCopy the code
6. Callback to the onResume and onRestart methods of the Activity
OnCreate determines if onResume is basically the same, or if it handles the information in the handleMessage of class H. When it is identified as RESUME_ACTIVITY, the handleResumeActivity is called
---->[ActivityThread#handleMessage]-------
case RESUME_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
SomeArgs args = (SomeArgs) msg.obj;
handleResumeActivity((IBinder) args.arg1, true, args.argi1 ! = 0,true,
args.argi3, "RESUME_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
---->[ActivityThread#handleResumeActivity]-------
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
if(! checkAndUpdateLifecycleSeq(seq, r,"resumeActivity")) {
return;
}
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration
r = performResumeActivity(token, clearHide, reason);
---->[ActivityThread#performResumeActivity]-------public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide, String reason) { ActivityClientRecord r = mActivities.get(token); / / a little... r.activity.performResume(); ---->[Activity#performResume]-------
final void performResume() { performRestart(); / / is called the first Restart method mFragments. ExecPendingActions (); mLastNonConfigurationInstances = null; mCalled =false;
// mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);
if(! mCalled) { ---->[Activity#performRestart]-------
final void performRestart() {// omit... mInstrumentation.callActivityOnRestart(this); // Now I see my old friend mInstrumentation, // You can see that the Activity life cycle is fully committed by mInstrumentation // even calling one of the onRestart methods of this class changes hands to mInstrumentation ---->[Instrumentation]#callActivityOnRestart]-------
public void callActivityOnRestart(Activity activity) {
activity.onRestart();
}
---->[Instrumentation#callActivityOnResume]-------
public void callActivityOnResume(Activity activity) {
activity.mResumed = true;
activity.onResume();
if(mActivityMonitors ! = null) { synchronized (mSync) { final int N = mActivityMonitors.size();for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
am.match(activity, activity, activity.getIntent());
}
}
}
}
---->[ActivityThread#handleResumeActivity]-------// After calling onResume, the window screen is displayedif(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(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit;if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if(a.mVisibleFromClient && ! a.mWindowAdded) { a.mWindowAdded =true;
wm.addView(decor, l);
}
Copy the code
7. Callback to the onStop method of the Activity
---->[ActivityThread#handleMessage]-------
case STOP_ACTIVITY_SHOW: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
SomeArgs args = (SomeArgs) msg.obj;
handleStopActivity((IBinder) args.arg1, true, args.argi2, args.argi3);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
---->[ActivityThread#handleStopActivity]-------
private void handleStopActivity(IBinder token, boolean show, int configChanges, int seq) {
ActivityClientRecord r = mActivities.get(token);
StopInfo info = new StopInfo();
performStopActivityInner(r, info, show, true."handleStopActivity"); / / a little... updateVisibility(r, show); / / a little... } ---->[ActivityThread#performStopActivityInner]-------private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown, boolean saveState, String reason) {// Omit... // One must first be paused before stopped... performPauseActivityIfNeeded(r, reason); // Pause logic // omit...if(! keepShown) { try { // Now we are idle. r.activity.performStop(false/*preserveWindow*/); / / stop -- -- -- - > [ActivityThread#performPauseActivityIfNeeded]-------Private void performPauseActivityIfNeeded (ActivityClientRecord r, String "reason) {/ / slightly... mInstrumentation.callActivityOnPause(r.activity); ---->[Instrumentation#callActivityOnPause]-------
public void callActivityOnPause(Activity activity) {
activity.performPause();
}
---->[Activity#callActivityOnPause]-------
final void performPause() {
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
mCalled = false; onPause(); / / a little... }Copy the code
8. Callback to the onDestroy method of the Activity
---->[ActivityThread#handleMessage]-------
case DESTROY_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy"); handleDestroyActivity((IBinder)msg.obj, msg.arg1 ! = 0, msg.arg2,false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
---->[ActivityThread#performDestroyActivity]-------
private void handleDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance);
---->[ActivityThread#performDestroyActivity]-------private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance) { ActivityClientRecord r = mActivities.get(token); / / a little... performPauseActivityIfNeeded(r,"destroy"); / / pauseif(! "R.s topped) {// If not stop, stop try {r.tivity. PerformStop (R.preserver window); / / a little... try { r.activity.mCalled =false;
mInstrumentation.callActivityOnDestroy(r.activity);
Copy the code