【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )

简介: 【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )

文章目录

前言

一、ActivityThread 类 handleLaunchActivity -> performLaunchActivity 方法

二、Instrumentation.newActivity 方法

三、AppComponentFactory.instantiateActivityCompat方法

四、ActivityThread.performLaunchActivity 方法后续细节

五、Instrumentation.callActivityOnCreate 方法

总结

前言

上一篇博客 【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 一 ) 分析了在 ActivityThread 主线程中将要调用 handleLaunchActivity 方法 , 启动新的 Activity ;






一、ActivityThread 类 handleLaunchActivity -> performLaunchActivity 方法


在 ActivityThread 的 handleLaunchActivity 中 , 调用了 performLaunchActivity 方法 ,


在 performLaunchActivity 方法中 , 调用了 mInstrumentation.newActivity 方法 , 正式创建 Activity 实例对象 ;


/**
 * 管理应用程序进程中主线程的执行、调度和执行活动、广播以及活动管理器请求的其他操作。
 *
 * {@hide}
 */
public final class ActivityThread extends ClientTransactionHandler {
    /**
     * Activity 启动的扩展实现。当服务器请求启动或重新启动时使用。
     */
    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
  // 创建页面 , 窗口初始化
        WindowManagerGlobal.initialize();
  // 启动 Activity 核心方法
        final Activity a = performLaunchActivity(r, customIntent);
        return a;
    }
    /**  Activity 启动的核心实现。 */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
    // 正式创建 Activity 对象  
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
        }
        return activity;
    }
}


完整代码参考 /frameworks/base/core/java/android/app/ActivityThread.java






二、Instrumentation.newActivity 方法


在 Instrumentation 的 newActivity 方法中 , 调用了 getFactory(pkg).instantiateActivity(cl, className, intent) 方法 , 创建 Activity ;


实际调用的是 AppComponentFactory 的 Activity instantiateActivityCompat(@NonNull ClassLoader cl, @NonNull String className, @Nullable Intent intent) 方法 ;


/**
 * 用于实现应用程序检测代码的基类。
 * 当在启用检测的情况下运行时,该类将在任何应用程序代码之前为您实例化,
 * 从而允许您监视系统与应用程序之间的所有交互。
 * 通过AndroidManifest.xml的<仪器仪表>标签。
 */
public class Instrumentation {
    /**
     * 执行流程{@link Activity}对象的实例化。默认实现提供正常的系统行为。
     *
     * @param cl 用于实例化对象的类加载器。
     * @param className 实现活动的类的名称对象
     * @param intent 指定要实例化的活动类的intent对象。
     *
     * @return The newly instantiated Activity object.
     */
    public Activity newActivity(ClassLoader cl, String className,
                                Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }
}


完整代码参考 /frameworks/base/core/java/android/app/Instrumentation.java ;






三、AppComponentFactory.instantiateActivityCompat方法


在 AppComponentFactory 的 instantiateActivityCompat 方法中 , 通过反射创建新的 Activity ;


由于不知道要启动哪个类 , 只能传入一个类名称 , 因此这里只能使用反射创建 Activity ;


/**
 * 使用androidx库的{@link android.app.AppComponentFactory}版本。
 *
 * 注意:这只适用于API 28+,不支持AppComponentFactory功能。
 */
@RequiresApi(28)
public class AppComponentFactory extends android.app.AppComponentFactory {
    /**
     * 允许应用程序覆盖活动的创建。这可以用于对这些类执行依赖项注入或类装入器更改等操作。
     *
     * 此方法仅用于提供用于实例化的挂钩。它不提供对活动对象的早期访问。
     * 返回的对象尚未初始化为上下文,不应用于与其他android API交互。
     *
     * @param cl 用于实例化的默认类加载器。
     * @param className 要实例化的类。
     * @intent 创建类的意图。
     */
    public @NonNull Activity instantiateActivityCompat(@NonNull ClassLoader cl,
                                                       @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        try {
            // 通过反射方式创建 Activity 
            return (Activity) cl.loadClass(className).getDeclaredConstructor().newInstance();
        } catch (InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException("Couldn't call constructor", e);
        }
    }
}


完整代码参考 /frameworks/support/compat/src/main/java/androidx/core/app/AppComponentFactory.java ;






四、ActivityThread.performLaunchActivity 方法后续细节


再次回到 ActivityThread 类的 performLaunchActivity 进行分析 ,


ContextImpl appContext = createBaseContextForActivity(r) 是应用中的 Context 上下文的唯一实现 ;


mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState) 代码就是触发调用 Activity 的 OnCreate 方法 ;


/**
 * 管理应用程序进程中主线程的执行、调度和执行活动、广播以及活动管理器请求的其他操作。
 *
 * {@hide}
 */
public final class ActivityThread extends ClientTransactionHandler {
    /**  Activity 启动的核心实现。 */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
    // 正式创建 Activity 对象  
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
        }
        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            if (activity != null) {
                activity.mCalled = false;
                if (r.isPersistable()) {
                  // 调用 Activity 的 onCreate 方法 
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                r.activity = activity;
            }
            mActivities.put(r.token, r);
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
        }
        return activity;
    }
}


完整代码参考 /frameworks/base/core/java/android/app/ActivityThread.java






五、Instrumentation.callActivityOnCreate 方法


Instrumentation 的 callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) 方法 , 主要是调用 Activity 的 performCreate 方法 , 之后会调用 Activity 的 onCreate 方法 ;


/**
 * 用于实现应用程序检测代码的基类。
 * 当在启用检测的情况下运行时,该类将在任何应用程序代码之前为您实例化,
 * 从而允许您监视系统与应用程序之间的所有交互。
 * 通过AndroidManifest.xml的<仪器仪表>标签。
 */
public class Instrumentation {
    /**
     * 执行对活动的{@link activity#onCreate}方法的调用。默认实现只是调用该方法。
     * 
     * @param activity 正在创建的活动。
     * @param icicle 要传递到的先前冻结状态(或null)
     * @param persistentState 以前的持久化状态(或null)
     */
    public void callActivityOnCreate(Activity activity, Bundle icicle,
                                     PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }
}


完整代码参考 /frameworks/base/core/java/android/app/Instrumentation.java ;


总结

截止到此处 , AMS 通过 Binder 机制调用 ActivityThread , 创建 Activity , 并调用 Activity 的 onCreate 方法 , 整个流程分析完毕 ;


目录
相关文章
|
3月前
|
算法 Java 数据库
Android 应用的主线程在什么情况下会被阻塞?
【10月更文挑战第20天】为了避免主线程阻塞,我们需要合理地设计和优化应用的代码。将耗时操作移到后台线程执行,使用异步任务、线程池等技术来提高应用的并发处理能力。同时,要注意避免出现死循环、不合理的锁使用等问题。通过这些措施,可以确保主线程能够高效地运行,提供流畅的用户体验。
120 2
|
4月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
111 6
|
4月前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
41 3
|
4月前
|
缓存 前端开发 Android开发
Android实战之如何截取Activity或者Fragment的内容?
本文首发于公众号“AntDream”,介绍了如何在Android中截取Activity或Fragment的屏幕内容并保存为图片。包括截取整个Activity、特定控件或区域的方法,以及处理包含RecyclerView的复杂情况。
41 3
|
4月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
33 0
|
9月前
|
数据库 Android开发 开发者
Android基础知识:请解释Activity的生命周期。
Android基础知识:请解释Activity的生命周期。
86 2
|
8月前
|
Android开发 UED
Android Activity的生命周期详解
Android Activity的生命周期详解
109 0
|
9月前
|
Android开发
Android Studio APP开发入门之活动Activity中启停活动页面的讲解及实战(附源码,包括Activity的启动结束、生命周期、跳转等)
Android Studio APP开发入门之活动Activity中启停活动页面的讲解及实战(附源码,包括Activity的启动结束、生命周期、跳转等)
174 0
|
Android开发
Android 中Activity和Fragment生命周期的具体变化详解
Android 中Activity和Fragment生命周期的具体变化详解
236 0
|
Android开发
Android中下拉通知栏,Activity会走哪些生命周期?
我们就可以做一个总结:当前Activity中,下拉通知栏,是不走任何生命周期的。
274 0

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 6
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 7
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 8
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 10
    Android学习自定义View(四)——继承控件(滑动时ListView的Item出现删除按钮)