Pregunta de la entrevista: ¿Qué patrón de diseño se usa para Intent en Android?

La respuesta es usar el patrón prototipo .

La ventaja del modo prototipo es que es conveniente copiar las propiedades de una instancia para su uso sin afectar la instancia original, su lógica radica en la implementación de Cloneablela interfaz .

Sin más preámbulos, veamos el código fuente clave Intentde :

 // 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) {
                 ...
             }
         }
     }
     ...
 }
复制代码

Se puede ver Intentque clone()la lógica implementada es llamar directamente a new y pasar su propia instancia en lugar de llamar a super.clone() para copiar.

La estrategia de copia predeterminada es COPY_MODE_ALL, como su nombre lo indica, construir con una copia completa de todos los atributos de la instancia de origen. Otras estrategias de copia COPY_MODE_FILTERse refieren a copiar solo los atributos relacionados con el Intent-filter , es decir, la información necesaria como acción , datos , tipo , componente , categoría , etc. utilizada para determinar el componente de destino inicial. Ignore la bandera de inicio , el paquete y otros datos.

 // 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;
             ...
         }
     }
 }
复制代码

Además COPY_MODE_HISTORY, la estrategia de copia no requiere datos históricos como paquetes , sino que conserva información básica como acciones y datos como indicadores de inicio .

 // 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;
                 }
             }
         }
     }
 }
复制代码

En resumen:

Modo de copia Acción y otros datos banderas y otros datos Paquete y otra historia
COPY_MODE_ALL
COPY_MODE_FILTER 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;
         }
     }
    复制代码

Supongo que te gusta

Origin juejin.im/post/7204013918958649405
Recomendado
Clasificación