Android点将台:颜值担当[-Activity-]

栏目: Android · 发布时间: 5年前

内容简介:activity生命周期测试总览(电脑上查看原图效果最佳)在该对象便是onCreate中的Bundle对象
至美不过回首,往事重重,顾来时,荆棘漫漫,血浸途中。
今铜衣铁靴,再行来路,任荆棘漫漫,唯落绿叶残枝。
                                     ----张风捷特烈 
复制代码

零、前言

1.本文的知识点

1).Acticity 生命周期 测试与分析

2).Activity间的 数据传递

3).Activity的四种 启动模式 详细分析

4).Activity的 跳转动画

5).Acticity的 生命周期源码 分析

2.Activity总览

Android点将台:颜值担当[-Activity-]
类名:Activity      父类:ContextThemeWrapper      修饰:public
包名:android.app   依赖类个数:115
内部类/接口个数:5
源码行数:7754       源码行数(除注释):3197
属性个数:20       方法个数:282       public方法个数:245
复制代码
Android点将台:颜值担当[-Activity-]

一、生命周期测试:

1.打开与关闭

Android点将台:颜值担当[-Activity-]

1.1.打开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.634 : LifeCycleActivity--onResume: 
复制代码

1.2.返回键关闭LifeCycleActivity:

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: 
复制代码

2.跳转普通Activity时两个Activity的生命周期

Android点将台:颜值担当[-Activity-]

2.1.在LifeCycleActivity中打开CommonActivity:

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: 
复制代码

2.2.CommonActivity返回键到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.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: 
复制代码

3.跳转对话框Activity时两个Activity的生命周期

Android点将台:颜值担当[-Activity-]

3.1.在LifeCycleActivity中打开DialogActivity:

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:
复制代码

3.2.DialogActivity返回键到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--onStop: 
2019-01-19 14:44:45.874 : DialogActivity--onDestroy: 
复制代码

4.LifeCycleActivity旋转屏幕(相当于关闭再开启):

Android点将台:颜值担当[-Activity-]
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点将台:颜值担当[-Activity-]

5、保存数据:

onStop 之前,会调用 onSaveInstanceState 其中有一个Bundle对象可以用来储存数据

该对象便是onCreate中的Bundle对象 savedInstanceState ,下图旋转屏时使用onSaveInstanceState

Android点将台:颜值担当[-Activity-]
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生命周期图示:

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

三、Activity间的数据传递

Android点将台:颜值担当[-Activity-]

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不能传递过大数据

Android点将台:颜值担当[-Activity-]
---->[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接返回值

Android点将台:颜值担当[-Activity-]
Android点将台:颜值担当[-Activity-]
---->[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.打开图库并设置图片

Android点将台:颜值担当[-Activity-]
//点击图片
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

Android点将台:颜值担当[-Activity-]
Android点将台:颜值担当[-Activity-]
依次打开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

Android点将台:颜值担当[-Activity-]
Android点将台:颜值担当[-Activity-]
依次打开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: Activity1 Task id is 82
依次返回
E/TASK_ID: Activity1 销毁
E/TASK_ID: Activity1 销毁
E/TASK_ID: Activity2 销毁
E/TASK_ID: Activity1 销毁
复制代码

3:singleTask模式: 对象唯一栈

整个栈中没有相同的实例,两次相同实例之间的Activity会被杀死(够霸道,我喜欢)

测试:Activity1为standard, Activity2 为singleTask

Android点将台:颜值担当[-Activity-]
Android点将台:颜值担当[-Activity-]
依次打开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

Android点将台:颜值担当[-Activity-]
Android点将台:颜值担当[-Activity-]
依次打开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 家族使用指南

默认 修改
Android点将台:颜值担当[-Activity-]
Android点将台:颜值担当[-Activity-]

1.代码实现Activity跳转

Android点将台:颜值担当[-Activity-]
/**
 * 作者:张风捷特烈<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)
    }
}
复制代码

2.跳转动画

---->[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>
复制代码

这样就可以了

3. 另外 还可以配置动画的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>
复制代码

五、Acticity的启动源码分析

一直想总结一下Activity的启动流程(),这里从Activity的生命周期入手

本文所讲述的启动流程主要是ActivityThread的H在接收到消息之后,即 handleMessage

至于消息如何传递过来的将在跨进程通信篇讲述

Android点将台:颜值担当[-Activity-]

1.谁是幕后黑手?

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

2.Activity是如何创建的?

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

Android点将台:颜值担当[-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();
 }
 
复制代码

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

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

Android点将台:颜值担当[-Activity-]
---->[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()方法的调用

Android点将台:颜值担当[-Activity-]
---->[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;
 }
复制代码

5.Activity的布局加载

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

Android点将台:颜值担当[-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,最顶层的视图
复制代码
Android点将台:颜值担当[-Activity-]

6.Activity的onResume和onRestart方法的回调

onCreate分析了,onResume基本是差不多,还是在H类中的

handleMessage中处理信息,当标识为RESUME_ACTIVITY时,调用 handleResumeActivity

Android点将台:颜值担当[-Activity-]
---->[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);
     }

复制代码

7.Activity的onStop方法的回调

Android点将台:颜值担当[-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");
//略...
    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();
    //略...
}
复制代码

8.Activity的onDestroy方法的回调

Android点将台:颜值担当[-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);
             //略...
            performPauseActivityIfNeeded(r, "destroy");//暂停
            if (!r.stopped) {//如果没stop,先stop
                try {
                    r.activity.performStop(r.mPreserveWindow);
            //略...
            try {
                r.activity.mCalled = false;
                mInstrumentation.callActivityOnDestroy(r.activity);
复制代码

后记:捷文规范

1.本文成长记录及勘误表

项目源码 日期 备注
V0.1--无 2018-1-21 Android点将台:颜值担当[-Activity-]

2.更多关于我

笔名 QQ 微信 爱好
张风捷特烈 1981462002 zdl1994328 语言
我的github 我的简书 我的CSDN 个人网站

3.声明

1----本文由张风捷特烈原创,转载请注明

2----欢迎广大编程爱好者共同交流

3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正

4----看到这里,我在此感谢你的喜欢与支持

Android点将台:颜值担当[-Activity-]

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

用户力:需求驱动的产品、运营和商业模式

用户力:需求驱动的产品、运营和商业模式

郝志中 / 机械工业出版社 / 2015-11-1 / 59.00

《用户力:需求驱动的产品、运营和商业模式》从用户需求角度深刻阐释了互联网产品设计、网络运营、商业模式构建的本质与方法论! 本书以“用户需求”为主线,先用逆向思维进行倒推,从本质的角度分析了用户的需求是如何驱动企业的产品设计、网络运营和商业模式构建的,将这三个重要部分进行了系统性和结构化的串联,然后用顺向思维进行铺陈,从实践和方法论的角度总结了企业究竟应该如围绕用户的真实需求来进行产品设计、网......一起来看看 《用户力:需求驱动的产品、运营和商业模式》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器