解读 PackageManager.resolveActivity

我们查看PackageManager类代码,发现PackageManager是一个抽象类。resolveActivity是一个抽象方法,并没有具体实现。

如下图:

所以我们要找到PackageManager的实现类才能找到resolveActivity的实现。我们在平常的开发中经常在Activity中或者用Context实例调用 getPackageManager。所以我们从Activity的getPackageManager找起。如果本类找不到实现声明,那说明在父类就声明了。

最后我们在ContextWrapper中找到了实现。

我们继续跟踪mBase.getPackageManager()。

我们知道Context.java是一个抽象类,并没有实际的实现。而ContextWrapper继承了Context抽象类,是Context的调用封装,具体的实现由传进来的mBase来实现。

我们来看一下ContextWrapper怎么把mBase传进来

public class ContextWrapper extends Context {
    @UnsupportedAppUsage
    Context mBase;
    public ContextWrapper(Context base) {
        mBase = base;
    }
    /**
     * Set the base context for this ContextWrapper.  All calls will then be
     * delegated to the base context.  Throws
     * IllegalStateException if a base context has already been set.
     *
     * @param base The new base context for this wrapper.
     */
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }
    /**
     * @return the base context as set by the constructor or setBaseContext
     */
    public Context getBaseContext() {
        return mBase;
    }

由代码可知,要么是构造函数传入,要么就是 attachBaseContext传入。实现可能是多样化的。

我们还是从我们最熟悉的Activity找起

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) {
        attachBaseContext(context);

可以看到Activity的attach传入了Conetxt。

我们在ActivityThread类的performLaunchActivity方法中找到了以下代码(具体怎么找到的有兴趣的可以了解一下 ActivtiyThread,因为内容太庞大,这里先不讲)

我们再看看这个传进入的appConetxt到底是什么?

 

 private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
        final int displayId = ActivityClient.getInstance().getDisplayId(r.token);
        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);

        // The rotation adjustments must be applied before creating the activity, so the activity
        // can get the adjusted display info during creation.
        if (r.mPendingFixedRotationAdjustments != null) {
            // The adjustments should have been set by handleLaunchActivity, so the last one is the
            // override for activity resources.
            if (mActiveRotationAdjustments != null && !mActiveRotationAdjustments.isEmpty()) {
                mResourcesManager.overrideTokenDisplayAdjustments(r.token,
                        mActiveRotationAdjustments.get(
                                mActiveRotationAdjustments.size() - 1).second);
            }
            r.mPendingFixedRotationAdjustments = null;
        }

我们又找到ContextImpl代码如下

 好了,追踪了半天原来就是 ContextImpl(有兴趣的可以详细了解)。这里我们也是一个验证 Context具体实现位置的过程。平时总听说context是抽象类,具体的实现在mBase。今天跟踪完也就明白了。

ContextImpl.java

@Override
    public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }
        final IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }
        return null;
    }

好了,我们最终找到了PackageManager的实现类,那就是 ApplicationPackageManager。

回到我们最初的本心是要查找PackageManager.resolveActivity的实现。

ApplicationPackageManager.java

@Override
    public ResolveInfo resolveActivity(Intent intent, int flags) {
        try {
            return mPM.resolveIntent(intent,
                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                    flags, UserId.myUserId());
        } catch (RemoteException e) {
            throw new RuntimeException("Package manager has died", e);
        }
    }

 

我们从前面的代码跟踪中可以得知

final IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

所以mPM 为ActivityThread.getPackageManager()

 可以看到是系统PackageManager的代理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闽农qq:994955138

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值