面试题:Android 中 Intent 采用了什么设计模式?
Posted TechMerger
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题:Android 中 Intent 采用了什么设计模式?相关的知识,希望对你有一定的参考价值。
答案是采用了原型模式。原型模式的好处在于方便地拷贝某个实例的属性进行使用、又不会对原实例造成影响,其逻辑在于对 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 相关的属性,即用来判断启动目标组件的 action、data、type、component、category 等必备信息。无视启动 flag、bundle 等数据。
// 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 Mode | action 等数据 | flags 等数据 | bundle 等历史 |
---|---|---|---|
COPY_MODE_ALL | YES | YES | YES |
COPY_MODE_FILTER | YES | NO | NO |
COPY_MODE_HISTORY | YES | YES | NO |
除了 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;
以上是关于面试题:Android 中 Intent 采用了什么设计模式?的主要内容,如果未能解决你的问题,请参考以下文章