美文网首页android 技术梳理
证明同一个应用只有一个 Application 对象实例

证明同一个应用只有一个 Application 对象实例

作者: jkwen | 来源:发表于2021-01-28 08:41 被阅读0次

接上一篇文章 根 Activity 的启动后续 内的一个疑问点,就是 handleBindApplication 方法里会创建 Application 的对象实例,并执行 onCreate 方法,而 performLaunchActivity 方法里看似也会创建 Application 的对象实例,并执行 onCreate。显然不会重复执行,那么是怎么保证的,如何能证明呢?

先来证明 makeApplication 方法调用者是同一个对象。

performLaunchActivity 里的 loadedApk 对象来源于下面方法里的 ActivityClientRecord r 对象。通过查看其构造方法看到,变量 packageInfo 最终由 ActivityThread 对象调用 getPackageInfoNoCheck 方法生成。

//LaunchActivityItem
@Override
public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
    mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
    mPendingResults, mPendingNewIntents, mIsForward,mProfilerInfo, client);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
//ActivityClientRecord
public ActivityClientRecord(...) {
    //
    this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo, compatInfo);
}

handleBindApplication 里的 loadedApk 对象也会由 ActivityThread 对象的 getPackageInfoNoCheck 方法生成。可见在这点上是相同的,那么他们会不会是同一个对象呢?getPackageInfoNoCheck 方法内部最终会调用下面这个方法。

//ActivityThread
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage) {
    //用来判断是否同一个进程,显然 aInfo 描述的进程就是应用进程
    //而不管是 handleBindApplication 还是 performLaunchActivity 所在的进程也都是应用进程
    //因此是 false
    final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
    synchronized(mResourcesManager) {
        WeakReference<LoadedApk> ref;
        if (differentUser) {
            ref = null;
        } else if (includeCode) {
            //includeCode 入参为 true,这里大概就是从 mPackages 里去找当前应用的 LoadedApk 对象
            //在 handleBindApplication 的时候应该是找不到的,需要新建
            ref = mPackages.get(aInfo.packageName);
        } else {
            ref = mResourcePackages.get(aInfo.packageName);
        }
        //在 performLaunchActivity 的时候,应该是有值的,直接获取 handleBindApplication 时创建的
        //LoadedApk 对象
        LoadedApk packageInfo = ref != null ? ref.get() : null;
        if (packageInfo == null || (packageInfo.mResources != null && !packageInfo.mResources.getAssets().isUpToDate())) {
            packageInfo = new LoadedApk(this, aInfo, compatInfo, baseLoader,
       securityViolation, includeCode &&(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, 
       registerPackage);
            if (differentUser) {
                // Caching not supported across users
            } else if (includeCode) {
                //刚才创建好的 LoadedApk 对象就会存在 mPackages 里
                mPackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
            } else {
                mResourcePackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
            }
        }
    }
    return packageInfo;
}

显然这么分析下来同一个应用包应该有着相同的 packageInfo。有了相同的 packageInfo,在创建应用进程并初始化 Application 后,Application 对象就被保存在了 packageInfo 对象里的 mApplication 变量。然后在启动 Activity 时,虽然看去也是 make Application,但内部做了防重复创建判断,这就会直接返回 mApplication。

不过上面结论成立的前提是,两处调用的方法入参要一致。其实这点只要结合应用进程的启动过程,Activity 的启动过程,抓住我们需要关注的参数,也可以知道对于同一个应用来说,那些表示应用的信息肯定是一致的,不然这就和我们实际使用不符合了。

相关文章

  • 证明同一个应用只有一个 Application 对象实例

    接上一篇文章 根 Activity 的启动后续[https://www.jianshu.com/p/1e2067d...

  • ASP.NET内置对象之Application对象

    Application对象是HttpApplicationState类的一个实例,它可以产生一个所有Web应用程序...

  • ASP.NET 中的Application详解

    Application对象是HttpApplicationState类的一个实例,Application状态是整个...

  • Egg.js框架学习

    框架内置基础对象 Application Application(简写为app) 是全局应用对象,在一个应用中,只...

  • Android设计模式—单例模式

    定义 确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 应用场景 确保某个类有且只有一个对象的场景...

  • 单例模式

    单例模式的目的 创建对象,确保对象的唯一性,在同一个系统中,对象只有一个实例.让类自己负责保存它的唯一实例,提供一...

  • Singleton

    单例模式 单例模式允许一个应用程序在每一个 JVM 实例中有且只有一个类的实例对象。 特征 一个JVM 实例内只有...

  • 【GeekBand】对于单例模式的研究

    单例模式的作用是解决"应用中只有一个实例"的一类问题,单例模式为了防止多个实例对象出现,只允许一个实例对象出现的一...

  • 组件中的data为什么是一个函数

    如果两个实例引用同一个对象,当其中一个实例的属性发生改变时,另一个实例属性也随之改变,只有当两个实例拥有自己的作用...

  • vue组件中的data不是一个对象而是一个函数

    如果两个实例引用同一个对象,当其中一个实例的属性发生改变时,另一个实例属性也随之改变,只有当两个实例拥有自己的作用...

网友评论

    本文标题:证明同一个应用只有一个 Application 对象实例

    本文链接:https://www.haomeiwen.com/subject/xinazktx.html