onStop之前,会调用onSaveInstanceState 其中有一个Bundle对象可以用来储存数据
该对象便是onCreate中的Bundle对象savedInstanceState,下图旋转屏时使用onSaveInstanceState

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OlZygS4x-1637137339039)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c5f3796cf?imageView2/0/w/1280/h/960/ignore-error/1)]

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生命周期图示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7oQ0wt1g-1637137339088)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c617de576?imageView2/0/w/1280/h/960/ignore-error/1)]

创建:onCreate():
|—可用于初始化工作,如setContentView界面资源、初始化数据
启动:onStart():
|—可见但无法交互
恢复:onResume():
|—恢复播放动画、音乐、视频等
暂停:onPause():
|—可做数据存储、停止动画、音乐、视频等
停止:onStop():
|—此时Activity不可见,可做视情况做些重量级回收工作,避免被Killed
销毁:onDestroy():
|—回收工作、资源释放
重现:onRestart():
|—可做一些恢复工作


三、Activity间的数据传递

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2aDJRQNx-1637137339089)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c616bac32?imageView2/0/w/1280/h/960/ignore-error/1)]

1.实体类: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()
    }
    }

2.传递基本数据类型、Serializable对象、Parcelable对象

注意Bundle不能传递过大数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oo7WXGQc-1637137339090)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c5fe2e1ab?imageView2/0/w/1280/h/960/ignore-error/1)]

---->[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)
}


3.FromActivity使用startActivityForResult打开ToActivity接返回值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bs70rcp2-1637137339091)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c78cdf091?imageView2/0/w/1280/h/960/ignore-error/1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hEdMRli5-1637137339092)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c85d22efc?imageView2/0/w/1280/h/960/ignore-error/1)]

---->[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)
}


4.打开图库并设置图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CWGKaQIC-1637137339092)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c8c636abd?imageView2/0/w/1280/h/960/ignore-error/1)]

//点击图片
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任务栈:Activity的活动序列

standard:标准栈
singleTop:顶复用栈
singleTask:对象唯一栈
singleInstance:单独实例栈


1.standard: 标准栈

当启动一个Activity,创建该Activity的新实例。入栈处于栈顶
测试:Activity1、2皆为standard

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1rxDvO32-1637137339093)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c9bf54ea4?imageView2/0/w/1280/h/960/ignore-error/1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JWHO6giH-1637137339094)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c9755e22d?imageslim)]

依次打开Activity1、2、2、1、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 销毁


2:singleTop模式:顶复用栈

在启动活动时若栈顶已经是该Activity,则直接使用它,不创建实例
测试:Activity1为standard, Activity2 为singleTop

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TJ3YltZe-1637137339094)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95ca57ac316?imageView2/0/w/1280/h/960/ignore-error/1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eMbtREKM-1637137339095)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95ca80b435e?imageslim)]

依次打开Activity1、2、2、1、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 销毁


3:singleTask模式:对象唯一栈

整个栈中没有相同的实例,两次相同实例之间的Activity会被杀死(够霸道,我喜欢)
测试:Activity1为standard, Activity2 为singleTask

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9xS0bPtG-1637137339095)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95cb8af191c?imageView2/0/w/1280/h/960/ignore-error/1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vb76g7hj-1637137339096)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95ccdc9544e?imageslim)]

依次打开Activity1、2、2、1、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 销毁


4:singleInstance 单独实例栈

启用一个新的活动栈来管理这个活动(够豪,够任性)
测试:Activity1为standard, Activity2 singleInstance

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pf5vkF2u-1637137339096)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95ceb75173d?imageView2/0/w/1280/h/960/ignore-error/1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CrDkll6p-1637137339097)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95cd0fed3c9?imageslim)]

依次打开Activity1、2、2、1、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方法


四、Activity的跳转动画

这里只是简单的四个平移动画,需要的更酷炫的效果道理是一样的
关于动画的更多知识,这里不废话了,可详见:Android 动画 Animator 家族使用指南

默认 修改

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UbkfZzPP-1637137339097)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95cba698d0a?imageView2/0/w/1280/h/960/format/png/ignore-error/1)]

|

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AATU7cgi-1637137339098)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95cc5c4fb8d?imageView2/0/w/1280/h/960/format/png/ignore-error/1)]

|


1.代码实现Activity跳转

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3OOUFMjd-1637137339099)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95cee8f8430?imageView2/0/w/1280/h/960/ignore-error/1)]

/**

  • 作者:张风捷特烈
  • 时间:2019/1/20/020:18:25
  • 邮箱:1981462002@qq.com
  • 说明:红色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);
    }
    }

/**

  • 作者:张风捷特烈
  • 时间:2019/1/20/020:18:25
  • 邮箱:1981462002@qq.com
  • 说明:绿色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)
    }
    }

2.跳转动画

---->[open_enter.xml]----------------------

<?xml version="1.0" encoding="utf-8"?>

---->[open_exit.xml]----------------------

<?xml version="1.0" encoding="utf-8"?>

---->[close_enter.xml----------------------

<?xml version="1.0" encoding="utf-8"?>

---->[close_exit.xml]----------------------

<?xml version="1.0" encoding="utf-8"?>

这样就可以了


3.另外还可以配置动画的style

用起来比在代码里方便些


五、Acticity的启动源码分析

一直想总结一下Activity的启动流程(),这里从Activity的生命周期入手
本文所讲述的启动流程主要是ActivityThread的H在接收到消息之后,即handleMessage
至于消息如何传递过来的将在跨进程通信篇讲述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fYdpDlJc-1637137339099)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95c3ab40672?imageView2/0/w/1280/h/960/ignore-error/1)]


1.谁是幕后黑手?

翻一下源码可以看出Context只是一个抽象类,定义了很多抽象方法
而ContextWrapper作为实现类将所有的工作甩手给了一个mBase的Context成员变量
ContextThemeWrapper寥寥百行代码,也不会是幕后黑手,现在台面上只有mBase

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ahMY5Fke-1637137339100)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95d07838d7c?imageView2/0/w/1280/h/960/ignore-error/1)]


2.Activity是如何创建的?

相信应该没有人去new Activity(),framework 层是如何创建Activity的实例呢?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LNm5K9zp-1637137339100)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95d1f384259?imageView2/0/w/1280/h/960/ignore-error/1)]

---->[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®;
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();
}


3.Application实例化及onCreate()方法调用

实现移到刚才创建Activity的performLaunchActivity方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zkVSgzmA-1637137339101)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95d040a5aab?imageView2/0/w/1280/h/960/ignore-error/1)]

---->[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
}


4.Activity的Context的创建及onCreate()方法的调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iRAeDWMX-1637137339101)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95d2a035a70?imageView2/0/w/1280/h/960/ignore-error/1)]

---->[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

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

开源分享完整内容戳这里

= 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;
}


5.Activity的布局加载

setContentView我们再熟悉不过了,看一下Activity源码是如何加载的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LfuljPjl-1637137339102)(https://user-gold-cdn.xitu.io/2019/4/23/16a4a95d3e06daa6?imageView2/0/w/1280/h/960/ignore-error/1)]

---->[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) {

}

//可见是通过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) {

Android点将台:颜值担当[-Activity-],项目实践相关推荐

  1. android 日历开发教程,android 开发教程之日历项目实践(三)

    二.创建样式 日历显示的表格线,使用 Cell 填充图形的边框来实现,为了统一,我们先定义边框线的颜色及线条精细. 另外还要定义一系统填充样式等. 创建 color: color_calendar_b ...

  2. 【渝粤教育】广东开放大学 Android移动开发项目实践 形成性考核 (58)

    题库查询系统退出 选择题 题目:下列选项中,属于Android Studio工具中创建项目时选择的按钮的是(). 答案: A.Start a new Android Studio project 题目 ...

  3. Kotlin项目实践指南(上)

    关于作者 郭孝星,程序员,吉他手,主要从事Android平台基础架构方面的工作,欢迎交流技术方面的问题,可以去我的Github提issue或者发邮件至guoxiaoxingse@163.com与我交流 ...

  4. XCoreRedux框架:Android UI组件化与Redux实践

    XCoreRedux框架:Android UI组件化与Redux实践 @author: 莫川 https://github.com/nuptboyzhb/ XCoreRedux源码+Demo:http ...

  5. android listview 导航条,Android侧边导航栏+ListView基础实践

    Android基础项目实践 文章首发于自己的github博客,https://lemonjuice98.github.io/ 本学期学习了Android的开发课程,期末也做了一款很萌新向的App作为课 ...

  6. 【转】Android 自己收集的开源项目和文章集合(持续更新至2018.12.17)

    2017-12-21 1.炫酷开屏动画框架 https://github.com/JoshuaRogue/FancyView 2.防京东,支付宝密码键盘和密码输入框 https://github.co ...

  7. Android第一行代码-Activity

    文章目录 Android第一行代码 Activity 1.Activity基本用法 2.创建和加载布局 加载布局(在Activity中加载布局) 在AndroidManifest文件中注册(所有的ac ...

  8. Android 自己收集的开源项目和文章集合

    1.仿QQ说说发图片选择框架  https://github.com/yaozs/ImageShowPicker 2.炫酷开屏动画框架  https://github.com/JoshuaRogue/ ...

  9. 即时通讯:XMPP项目实践-微聊

    即时通讯系列阅读 即时通讯基础 即时通讯:XMPP基础 即时通讯:XMPP项目实践-微聊 Smack类库最好的学习资料 1. 项目简介 做一个类似QQ 的通讯工具,要求有注册.登录.添加好友.添加分组 ...

  10. Android正向开发(一) Activity

    Android 正向开发--Activity 活动(Activity)是什么 Activity的基本用法 创建活动 手动创建 Activity 界面相关 创建布局,添加按钮 加载布局 补:定义& ...

最新文章

  1. Linux重定向和管道符使用避坑指南
  2. 使用合成数据集来做目标检测:目标检测的介绍
  3. 微软熊辰炎:如何利用图神经网络解决半结构化数据问题?
  4. 广西互联网金融平台系列-7条奇怪的投资数据
  5. java连接kafka api_Kafka-JavaAPI(Producer And Consumer)
  6. java 网站转app_java – 将现有Web应用程序转换为桌面应用程序
  7. 按类别组织的Python主要内置对象类型
  8. pycharm新建python的快捷键_Python基础之PyCharm 的初始设置
  9. 算法笔记_面试题_19.链表_模板及示例十几道
  10. Windows server 2003设置IP安全策略批处理脚本
  11. jedate选中日期后关闭弹层_jeDate日期控件的使用以及选中后点确定按钮关闭功能...
  12. creo数控编程怎么样_Creo4.0数控加工教程
  13. Mockplus组件样式库一键解决风格复用
  14. excel多列多行堆叠成多列一行_excel行列转换-Excel一行转多行、一列转多列,记住这4条可套用的模板公式...
  15. 关于Excel被保护的工作表忘记密码的强制解除办法
  16. 利用一个竞态漏洞root三星s8的方法
  17. 最佳化三维建模与重构中的神经网络先验
  18. linux netgear usb,家用四槽位 NETGEAR ReadyNAS NV+评测
  19. 微软携手云南打造软件产业高地 签约建立微软IT学院
  20. Flutter学习第十四天:Flutter类似于淘宝的首页照片墙功能,让你的界面更加美观灵活?

热门文章

  1. 记第一次实战靶场的经验
  2. android 声音同步 测试,基于FFmpeg和Android的音视频同步播放实现
  3. JWT signature does not match locally computed signature. JWT validity cannot be asserted and should
  4. csv日文乱码问题的解决
  5. 手气不错 跳过搜索 谷歌 Google
  6. OV7725之AL422B-FIFO及摄像头的驱动原理
  7. 阿里云发布企业云原生IT成本治理方案:五大能力加速企业 FinOps 进程
  8. [CSP-S模拟测试]:砍树(数学+模拟)
  9. OpenHarmony代码下载编译流程记录
  10. 斐讯N1安装Armbian+lnmp+omv+docker