面试题:Android 中 Intent 采用了什么设计模式?

文章详细解析了Android系统中Intent类如何实现原型模式,通过clone()方法创建新的Intent实例,同时介绍了COPY_MODE_ALL、COPY_MODE_FILTER和COPY_MODE_HISTORY三种不同的拷贝策略,以及Bundle和ComponentName等其他类的类似实现。此外,还提及了原型模式不一定需实现Cloneable接口,如Bitmap的copy()方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

答案是采用了原型模式。原型模式的好处在于方便地拷贝某个实例的属性进行使用、又不会对原实例造成影响,其逻辑在于对 Cloneable 接口的实现。

话不多说看下 Intent 的关键源码:

// frameworks/base/core/java/android/content/Intent.java
public class Intent implements Parcelable, Cloneable {
    ...
    private static final int COPY_MODE_ALL = 0;
    private static final int COPY_MODE_FILTER = 1;
    private static final int COPY_MODE_HISTORY = 2;

    @Override
    public Object clone() {
        return new Intent(this);
    }

    public Intent(Intent o) {
        this(o, COPY_MODE_ALL);
    }

    private Intent(Intent o, @CopyMode int copyMode) {
        this.mAction = o.mAction;
        this.mData = o.mData;
        this.mType = o.mType;
        this.mIdentifier = o.mIdentifier;
        this.mPackage = o.mPackage;
        this.mComponent = o.mComponent;
        this.mOriginalIntent = o.mOriginalIntent;
        ...

        if (copyMode != COPY_MODE_FILTER) {
            ...
            if (copyMode != COPY_MODE_HISTORY) {
                ...
            }
        }
    }
    ...
}

可以看到 Intent 实现的 clone() 逻辑是直接调用了 new 并传入了自身实例,而非调用 super.clone() 进行拷贝。

默认的拷贝策略是 COPY_MODE_ALL,顾名思义,将完整拷贝源实例的所有属性进行构造。其他的拷贝策略是 COPY_MODE_FILTER 指的是只拷贝跟 Intent-filter 相关的属性,即用来判断启动目标组件的 actiondatatypecomponentcategory 等必备信息。无视启动 flagbundle 等数据。

// frameworks/base/core/java/android/content/Intent.java
public class Intent implements Parcelable, Cloneable {
    ...
    public @NonNull Intent cloneFilter() {
        return new Intent(this, COPY_MODE_FILTER);
    }

    private Intent(Intent o, @CopyMode int copyMode) {
        this.mAction = o.mAction;
        ...

        if (copyMode != COPY_MODE_FILTER) {
            this.mFlags = o.mFlags;
            this.mContentUserHint = o.mContentUserHint;
            this.mLaunchToken = o.mLaunchToken;
            ...
        }
    }
}

还有中拷贝策略是 COPY_MODE_HISTORY,不需要 bundle 等历史数据,保留 action 等基本信息和启动 flag 等数据。

// frameworks/base/core/java/android/content/Intent.java
public class Intent implements Parcelable, Cloneable {
    ...
    public Intent maybeStripForHistory() {
        if (!canStripForHistory()) {
            return this;
        }
        return new Intent(this, COPY_MODE_HISTORY);
    }

    private Intent(Intent o, @CopyMode int copyMode) {
        this.mAction = o.mAction;
        ...

        if (copyMode != COPY_MODE_FILTER) {
            ...
            if (copyMode != COPY_MODE_HISTORY) {
                if (o.mExtras != null) {
                    this.mExtras = new Bundle(o.mExtras);
                }
                if (o.mClipData != null) {
                    this.mClipData = new ClipData(o.mClipData);
                }
            } else {
                if (o.mExtras != null && !o.mExtras.isDefinitelyEmpty()) {
                    this.mExtras = Bundle.STRIPPED;
                }
            }
        }
    }
}

总结起来:

Copy Modeaction 等数据flags 等数据bundle 等历史
COPY_MODE_ALLYESYESYES
COPY_MODE_FILTERYESNONO
COPY_MODE_HISTORYYESYESNO

除了 Intent,Android 源码中还有很多地方采用了原型模式。

  • Bundle 也实现了 clone(),提供了 new Bundle(this) 的处理:

    public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
        ...
        @Override
        public Object clone() {
            return new Bundle(this);
        }
    }
    
  • 组件信息类 ComponentName 也在 clone() 中提供了类似的实现:

    public final class ComponentName implements Parcelable, Cloneable, Comparable<ComponentName> {
        ...
        public ComponentName clone() {
            return new ComponentName(mPackage, mClass);
        }
    }
    
  • 工具类 IntArray 亦是如此:

    public class IntArray implements Cloneable {
        ...
        @Override
        public IntArray clone() {
            return new IntArray(mValues.clone(), mSize);
        }
    }
    

原型模式也不一定非得实现 Cloneable,提供了类似的实现即可。比如:

  • Bitmap 没有实现该接口但提供了 copy(),内部将传递原始 Bitmap 在 native 中的对象指针并伴随目标配置进行新实例的创建:

    public final class ComponentName implements Parcelable, Cloneable, Comparable<ComponentName> {
        ...
        public Bitmap copy(Config config, boolean isMutable) {
            ...
            noteHardwareBitmapSlowCall();
            Bitmap b = nativeCopy(mNativePtr, config.nativeInt, isMutable);
            if (b != null) {
                b.setPremultiplied(mRequestPremultiplied);
                b.mDensity = mDensity;
            }
            return b;
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

TechMerger

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

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

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

打赏作者

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

抵扣说明:

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

余额充值