我的全部文章整理在此篇,將陸續更新收錄:知無涯,行者之路莫言終(個人編程之路)java
[1].Acticity生命週期測試與分析
[2].Activity間的[數據傳遞]
[3].Activity的四種[啓動模式]詳細分析
[4].Activity的[跳轉動畫]
[5].Acticity的生命[週期源碼]分析
複製代碼
類名:Activity 父類:ContextThemeWrapper 修飾:public
包名:android.app 依賴類個數:115
內部類/接口個數:5
源碼行數:7754 源碼行數(除註釋):3197
屬性個數:20 方法個數:282 public方法個數:245
複製代碼
2019-01-19 14:06:10.614 : LifeCycleActivity--onCreate:
2019-01-19 14:06:10.617 : LifeCycleActivity--onStart:
2019-01-19 14:06:10.634 : LifeCycleActivity--onResume:
複製代碼
2019-01-19 14:08:52.675 : LifeCycleActivity--onPause:
2019-01-19 14:08:53.247 : LifeCycleActivity--onStop:
2019-01-19 14:08:53.249 : LifeCycleActivity--onDestroy:
複製代碼
2019-01-19 14:15:57.454 : LifeCycleActivity--onPause:
2019-01-19 14:15:57.495 : CommonActivity--onCreate:
2019-01-19 14:15:57.497 : CommonActivity--onStart:
2019-01-19 14:15:57.501 : CommonActivity--onResume:
2019-01-19 14:15:58.256 : LifeCycleActivity--onStop:
複製代碼
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.963 : CommonActivity--onStop:
2019-01-19 14:19:09.963 : CommonActivity--onDestroy:
複製代碼
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:
複製代碼
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--onStop:
2019-01-19 14:44:45.874 : DialogActivity--onDestroy:
複製代碼
2019-01-19 14:46:28.619 : LifeCycleActivity--onPause:
2019-01-19 14:46:28.639 : 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:
複製代碼
activity生命週期測試總覽(電腦上查看原圖效果最佳)android
在
onStop
以前,會調用onSaveInstanceState
其中有一個Bundle對象能夠用來儲存數據
該對象即是onCreate中的Bundle對象savedInstanceState
,下圖旋轉屏時使用onSaveInstanceState編程
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: ")
}
複製代碼
之所謂生命週期,就是從生到死有明確的回調函數
函數在不一樣狀態下由安卓框架層進行回調,簡化開發流程。
讓開發者使用時只須要關注Activity狀態,根據狀態構建邏輯,而無需深刻底層實現。
Activity主要有7個生命週期回調函數,以下,是最經典的Activity生命週期圖示:bash
建立:onCreate():
|---可用於初始化工做,如setContentView界面資源、初始化數據
啓動:onStart():
|---可見但沒法交互
恢復:onResume():
|---恢復播放動畫、音樂、視頻等
暫停:onPause():
|---可作數據存儲、中止動畫、音樂、視頻等
中止:onStop():
|---此時Activity不可見,可作視狀況作些重量級回收工做,避免被Killed
銷燬:onDestroy():
|---回收工做、資源釋放
重現:onRestart():
|---可作一些恢復工做
複製代碼
Person
/**
* 做者:張風捷特烈
* 時間:2018/4/26:12:13
* 郵箱:1981462002@qq.com
* 說明:簡單實體Person
*/
class Person(var name: String?, var age: Int) : Serializable {
override fun toString(): String {
return "Person{" +
"name='" + name + '\''.toString() + ", age=" + age + '}'.toString() } } 複製代碼
注意Bundle不能傳遞過大數據app
---->[FromActivity點擊]-----------
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", "張風捷特烈")
startActivity(intent)
---->[ToActivity接收使用]-----------
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)
}
複製代碼
---->[FromActivity]-----------
companion object {
private const val DATA_CODE = 0x0001
}
//點擊時
id_btn_for_result.setOnClickListener {
val intent = Intent(this, ToActivity::class.java)
startActivityForResult(intent, DATA_CODE)
}
//回調
override fun onActivityResult(requestCode: Int, resultCode: Int, data: 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.toString())
}
}
}
---->[ToActivity傳遞數據給FromActivity]-----------
private fun backWithData() {
val jt = Person("捷特", 24)
val intent = Intent()
intent.putExtra("data", "我是ToActivity的數據")
val bundle = Bundle()
bundle.putSerializable("person", jt)
intent.putExtra("To", bundle)
setResult(Activity.RESULT_OK, intent)
}
複製代碼
//點擊圖片
id_iv_icon.setOnClickListener {
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*";
startActivityForResult(intent, 0)
}
//處理結果
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 0 && resultCode == Activity.RESULT_OK) {//成功
val selectedImage = data?.data ?: return
val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
val cursor = contentResolver.query(// 獲取選擇照片的數據視圖
selectedImage, filePathColumn, null, null, null
)
cursor.moveToFirst()
// 從數據視圖中獲取已選擇圖片的路徑
val columnIndex = cursor.getColumnIndex(filePathColumn[0])
val picturePath = cursor.getString(columnIndex)
cursor.close()
id_iv_icon.setImageBitmap(BitmapFactory.decodeFile(picturePath))
}
}
複製代碼
Activity任務棧:Activity的活動序列框架
standard:標準棧
singleTop:頂複用棧
singleTask:對象惟一棧
singleInstance:單獨實例棧
複製代碼
標準棧
當啓動一個Activity,建立該Activity的新實例。入棧處於棧頂
測試:Activity一、2皆爲standardide
依次打開Activity一、二、二、一、2
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: Activity1 Task id is 89
E/TASK_ID: Activity2 Task id is 89
依次返回
E/TASK_ID: Activity2 銷燬
E/TASK_ID: Activity1 銷燬
E/TASK_ID: Activity2 銷燬
E/TASK_ID: Activity2 銷燬
E/TASK_ID: Activity1 銷燬
複製代碼
頂複用棧
在啓動活動時若棧頂已是該Activity,則直接使用它,不建立實例
測試:Activity1爲standard, Activity2 爲singleTop函數
依次打開Activity一、二、二、一、2
E/TASK_ID: Activity1 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
依次返回
E/TASK_ID: Activity2 銷燬
E/TASK_ID: Activity1 銷燬
E/TASK_ID: Activity2 銷燬
E/TASK_ID: Activity1 銷燬
複製代碼
對象惟一棧
整個棧中沒有相同的實例,兩次相同實例之間的Activity會被殺死(夠霸道,我喜歡)
測試:Activity1爲standard, Activity2 爲singleTaskoop
依次打開Activity一、二、二、一、2
E/TASK_ID: Activity1 Task id is 94
E/TASK_ID: Activity2 Task id is 94
E/TASK_ID: Activity1 Task id is 94
E/TASK_ID: Activity1 銷燬
依次返回
E/TASK_ID: Activity2 銷燬
E/TASK_ID: Activity1 銷燬
複製代碼
單獨實例棧
啓用一個新的活動棧來管理這個活動(夠豪,夠任性)
測試:Activity1爲standard, Activity2 singleInstance源碼分析
依次打開Activity一、二、二、一、2
E/TASK_ID: Activity1 Task id is 115
E/TASK_ID: Activity2 Task id is 116
E/TASK_ID: Activity1 Task id is 115
依次返回
E/TASK_ID: Activity2 銷燬
E/TASK_ID: Activity1 銷燬
E/TASK_ID: Activity1 銷燬
複製代碼
注意一點:
singleTask模式和singleTop模式時,非第一次啓動,不會調用onCreate方法!
但會走onNewIntent方法
複製代碼
這裏只是簡單的四個平移動畫,須要的更酷炫的效果道理是同樣的
關於動畫的更多知識,這裏不廢話了,可詳見:Android 動畫 Animator 家族使用指南
默認 | 修改 |
---|---|
/**
* 做者:張風捷特烈<br></br>
* 時間:2019/1/20/020:18:25<br></br>
* 郵箱:1981462002@qq.com<br></br>
* 說明:紅色Activity
*/
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);
}
}
/**
* 做者:張風捷特烈<br></br>
* 時間:2019/1/20/020:18:25<br></br>
* 郵箱:1981462002@qq.com<br></br>
* 說明:綠色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()//右移入---右移出
overridePendingTransition(R.anim.close_enter, R.anim.close_exit)
}
}
複製代碼
---->[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>
複製代碼
這樣就能夠了
另外
還能夠配置動畫的style用起來比在代碼裏方便些
<!--配置Activity進出動畫-->
<style name="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>
複製代碼
一直想總結一下Activity的啓動流程(),這裏從Activity的生命週期入手
本文所講述的啓動流程主要是ActivityThread的H在接收到消息以後,即handleMessage
至於消息如何傳遞過來的將在跨進程通訊篇講述
翻一下源碼能夠看出Context只是一個抽象類,定義了不少抽象方法
而ContextWrapper做爲實現類將全部的工做甩手給了一個mBase的Context成員變量
ContextThemeWrapper寥寥百行代碼,也不會是幕後黑手,如今檯面上只有mBase
複製代碼
相信應該沒有人去
new Activity()
,framework 層是如何建立Activity的實例呢?
---->[ActivityThread]-------
final H mH = new H();
---->[ActivityThread$H#handleMessage]-------
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {//啓動Activity
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
//r:記錄Activity的一些描述信息
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
//經過r來獲取包信息
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//開啓的核心方法(劃重點)
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
---->[ActivityThread#handleLaunchActivity]-------
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
//在這裏返回來Activity的對象
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);
//略...
}
---->[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();
//此處可見是mInstrumentation建立的Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
//略...
return activity;
}
---->[Instrumentation#newActivity]-------
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
//經過類加載器生成Activity實例
return (Activity)cl.loadClass(className).newInstance();
}
複製代碼
實現移到剛纔建立Activity的
performLaunchActivity
方法
---->[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());
//略...
try {
//建立Activity以後經過ActivityClientRecord的packageInfo對象的makeApplication
//來建立Application,packageInfo是一個LoadedApk類的對象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
//略...
}
---->[LoadedApk#makeApplication]-------
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
//略...
try {
java.lang.ClassLoader cl = getClassLoader();
//略...
//這裏ContextImpl出場了
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//這裏經過mInstrumentation的newApplication方法建立Application對象
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
//將建立的Application設置到appContext上
appContext.setOuterContext(app);
}
//略...
//mActivityThread將當前app加入mAllApplications列表中
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
//這時調用application的OnCreate方法
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 {
//也是經過反射獲取Application實例
return newApplication(cl.loadClass(className), context);
}
---->[Instrumentation#callApplicationOnCreate]-------
public void callApplicationOnCreate(Application app) {
app.onCreate();//直接調用onCreate onCreate
}
複製代碼
---->[ActivityThread#performLaunchActivity]-------
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
//Activity的一些配置信息
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;
}
//將Activity和window綁定
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);
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) {
//略...
//看這裏appContext是ContextImpl類對象,Activity的Context幕後黑手出現了
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.token, 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*/); //這裏的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; } 複製代碼
setContentView咱們再熟悉不過了,看一下Activity源碼是如何加載的
---->[Activity#setContentView]-----------------
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
//可見是經過Window的setContentView來加載佈局的,
//經過attach方法知道這個window對象是PhoneWindow類
---->[PhoneWindow#setContentView]-----------------
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
if (mContentParent == null) {
installDecor();//初始化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);
}
}
if (mContentParent == null) {
//經過DecorView來建立mContentParent
mContentParent = generateLayout(mDecor);
//對mDecor進行處理,略...
---->[PhoneWindow#generateDecor]-----------------
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
>DecorView何許人也?
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker
可見是一個幀佈局FrameLayout,最頂層的視圖
複製代碼
onCreate分析了,onResume基本是差很少,仍是在H類中的
handleMessage中處理信息,當標識爲RESUME_ACTIVITY時,調用handleResumeActivity
---->[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);
//略...
r.activity.performResume();
---->[Activity#performResume]-------
final void performResume() {
performRestart();//可見是先調用了Restart方法
mFragments.execPendingActions();
mLastNonConfigurationInstances = null;
mCalled = false;
// mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);
if (!mCalled) {
---->[Activity#performRestart]-------
final void performRestart() {
//略...
mInstrumentation.callActivityOnRestart(this);
//又看到老朋友mInstrumentation了,
//能夠看到Activity的生命週期由mInstrumentation全權負責
//就連調用本類的一個onRestart方法都要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]-------
//回調onResume後進行window界面顯示
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();
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);
}
複製代碼
---->[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");
//略...
updateVisibility(r, show);
//略...
}
---->[ActivityThread#performStopActivityInner]-------
private void performStopActivityInner(ActivityClientRecord r,
StopInfo info, boolean keepShown, boolean saveState, String reason) {
//略...
// One must first be paused before stopped...
performPauseActivityIfNeeded(r, reason);//暫停邏輯
//略...
if (!keepShown) {
try {
// Now we are idle.
r.activity.performStop(false /*preserveWindow*/);//中止
---->[ActivityThread#performPauseActivityIfNeeded]-------
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
//略...
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();
//略...
}
複製代碼
---->[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);
//略...
performPauseActivityIfNeeded(r, "destroy");//暫停
if (!r.stopped) {//若是沒stop,先stop
try {
r.activity.performStop(r.mPreserveWindow);
//略...
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnDestroy(r.activity);
複製代碼