这篇文章主要介绍了Android面试Intent采用的设计模式是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇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 | 
Android 源码中还有很多地方采用了原型模式
除了
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;
     }
 }