La diferencia entre serializable y parcelable

Acabo de ver el código fuente de Intent hoy y descubrí que implementa la interfaz Parcelable. De repente recordé que hay una interfaz Serializable en Java, así que quiero aprovechar esta oportunidad para hablar sobre mis puntos de vista sobre estas dos interfaces.

En Android, todos sabemos que no podemos pasar objetos directamente a la actividad. Para poder pasar objetos, estos objetos deben implementar la interfaz serializable o la interfaz parcelable. Entonces, ¿cuál es la diferencia entre los dos? Primero echemos un vistazo a la interfaz serializable.

Serializable


Primero mire la definición de la interfaz serializable en el código fuente de Java:

package java.io;
public interface Serializable {
}

Serializable es una interfaz estándar de Java. De la definición de la interfaz, podemos ver que está ubicada en el directorio del paquete java.io. No define ningún método o variable. Solo se usa para determinar la semántica de la serialización. Entonces podemos implementar esta interfaz y agregar métodos nosotros mismos. Pero el mecanismo de serialización usa la reflexión para construir objetos serializados, por lo que el rendimiento es lento. Y crea una gran cantidad de objetos temporales, lo que provoca un GC considerable. Esta interfaz es relativamente fácil de implementar. Veamos un ejemplo:

class SeObject implements Serializable {

    private String name;
    private int age;

    public SeObject(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

Aquí definí un SeObject, implementé esta interfaz, definí un nombre y una edad, e implementé un constructor y métodos getter. Planeo pasar este objeto SeObject entre actividades. Veamos cómo la primera actividad pasa el objeto SeObject:

    public void startActivity(View view) {
        Intent intent = new Intent(this, SecondActivity.class);
        SeObject seObject = new SeObject("Leon", 28);
        Bundle bundle = new Bundle();
        bundle.putSerializable("Object", seObject);
        intent.putExtras(bundle);
        startActivity(intent);
    }

Primero, se define un Botón en el diseño de la primera actividad, y la propiedad onClick se establece en startActivity, de modo que se llamará al método anterior cuando se haga clic en el Botón. Como puede ver, primero definí un Bundle, pasé el objeto SeObject al método putSerializable, puse el objeto bundle en el Intent y lo pasé a SecondActivity. Veamos cómo SecondActivity.java obtiene este objeto SeObject:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Intent intent = getIntent();
        Bundle bundle = intent.getExtras();
        SeObject seObject = (SeObject) bundle.getSerializable("Object");
        Log.d("SecondActivity", "Name is " + seObject.getName() + ", age is " +         
             seObject.getAge());
    }

El LOG impreso es el siguiente: 

D/SecondActivity( 7760): Name is Leon, age is 28

Todos comparan cuidadosamente los códigos de estos dos archivos, y los estudiantes muy cuidadosos deben encontrar que existe una relación correspondiente:

putExtras -> getExtras;putSerializable -> getSerializable

Al obtener un objeto SeObject, primero llame a intent.getExtras () para obtener el objeto Bundle, y luego llame a bundle.getSerializable para leer el objeto SeObject del objeto Bundle, que es exactamente el orden opuesto al de poner objetos SeObject en el primer Recuerde que esta secuencia es fácil de implementar en el futuro para pasar objetos personalizados en el Intent y no es fácil cometer errores. Pero después de mi propia verificación, el objeto SeObject también se puede obtener de la siguiente manera:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Intent intent = getIntent();
        SeObject seObject = (SeObject) intent.getSerializableExtra("Object");
        Log.d("SecondActivity", "11 Name is " + seObject.getName() + ", age is " + 
             seObject.getAge());
    }

(Pero personalmente me gusta el primer método de implementación, no es fácil cometer errores, especialmente cuando se pasan varios objetos, puedes hacerlo según tus propios hábitos).

Veamos nuevamente la interfaz Parcelable.

Parcelable


Veamos primero la definición de la interfaz Parcelable:

package android.os;
public interface Parcelable {
    public void writeToParcel(Parcel dest, @WriteFlags int flags);
    public static final int PARCELABLE_WRITE_RETURN_VALUE = 0x0001;
    public @ContentsFlags int describeContents();
    public interface Creator<T> {
        /**
         * Create a new instance of the Parcelable class, instantiating it
         * from the given Parcel whose data had previously been written by
         * {@link Parcelable#writeToParcel Parcelable.writeToParcel()}.
         * 
         * @param source The Parcel to read the object's data from.
         * @return Returns a new instance of the Parcelable class.
         */
        public T createFromParcel(Parcel source);
        
        /**
         * Create a new array of the Parcelable class.
         * 
         * @param size Size of the array.
         * @return Returns an array of the Parcelable class, with every entry
         * initialized to null.
         */
        public T[] newArray(int size);
    }

Aquí solo enumero una parte del código fuente. Como puede ver en el código fuente, Parcelable se encuentra en el directorio del paquete android.os. No solo define algunas variables y métodos, sino que también define una interfaz interna Creator <T> . El proceso Parcelable es mucho más rápido que el proceso de serialización. Una de las razones es que aclaramos el proceso de serialización en lugar de usar la reflexión para inferirlo. El código ha sido altamente optimizado para esto. Veamos un ejemplo de Parceable:

class ParObject implements Parcelable {

    private String name;
    private int age;


    public ParObject(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public ParObject(Parcel source) {
        name = source.readString();
        age = source.readInt();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
    
    public static final Creator<ParObject> CREATOR = new Creator<ParObject>() {
        @Override
        public ParObject[] newArray(int size) {
            return new ParObject[size];
        }

        @Override
        public ParObject createFromParcel(Parcel source) {
            return new ParObject(source);
        }
    };

}

La implementación de Parcelable de Android permite leer y escribir desde Parcel, y Parcel contiene datos planos en el contenedor de mensajes. Si queremos convertir objetos Java en Parcelable, la mejor manera es implementar la interfaz Parcelable como se indicó anteriormente y anular el método writeToParcel. El primer paso es anular el método writeToParcel para escribir todos los miembros del objeto en el objeto de parcela; el segundo paso es crear un objeto Parcelable.Creator estático para lograr la deserialización. 

public void startActivity(View view) {    
        ParObject parObject = new ParObject("Leon", 27);
        Intent mIntent = new Intent(this, SecondActivity.class);
        Bundle bundle = new Bundle();
        bundle.putParcelable("object", parObject);
        mIntent.putExtras(bundle);
        startActivity(mIntent);
    }
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Intent intent = getIntent();
        Bundle bundle = intent.getExtras();
        ParObject parObject = bundle.getParcelable("object");
        Log.d("SecondActivity", "the Name is " + parObject.getName() + ", age is " + 
             parObject.getAge());
    }

El registro impreso es el siguiente:

10-26 15:00:58.694 24199 24199 D SecondActivity: the Name is Leon, age is 27

Eche un vistazo más de cerca, de hecho, el uso es similar a Serializable, la única diferencia es que putSerializable se reemplaza por putParcelable, y luego se cambia a getParcelable cuando se obtienen objetos de la segunda actividad.

Alguien puede preguntar, ¿es esta la diferencia? Por supuesto, no solo, dado que Android proporciona un mecanismo más poderoso para transferir objetos, debe poder hacer más, es decir, Parcelable puede transferir una lista de múltiples objetos:

public void startActivity(View view) {       
        Intent mIntent = new Intent(this, SecondActivity.class);
        Bundle bundle = new Bundle();
        ArrayList<ParObject> list = new ArrayList<>(2);
        list.add(new ParObject("Leon_1", 27));
        list.add(new ParObject("Leon_2", 28));
        bundle.putParcelableArrayList("object", list);
        mIntent.putExtras(bundle);
        startActivity(mIntent);
    }
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Intent intent = getIntent();
        Bundle bundle = intent.getExtras();
        ArrayList<ParObject> list = bundle.getParcelableArrayList("object");
        if (list != null) {
            Log.d("SecondActivity", "size is " + list.size());
            for (ParObject parObject : list) {
                Log.d("SecondActivity", "Name is " + parObject.getName() + ", age is " + 
                     parObject.getAge());
            }
        }

    }

El registro impreso es el siguiente:

10-26 15:12:28.023 26428 26428 D SecondActivity: size is 2
10-26 15:12:28.023 26428 26428 D SecondActivity: Name is Leon_1, age is 27
10-26 15:12:28.023 26428 26428 D SecondActivity: Name is Leon_2, age is 28

Puede verse claramente que se pasa una ArrayList de la primera actividad y la Lista se obtiene con éxito en la segunda actividad.

Comprobemos si el paquete proporciona una lista que transmite objetos serializables.

 La respuesta es no. Echemos un vistazo a las otras interfaces para transferir objetos Parcelable:

Como puede ver, además de transmitir List, también puede transmitir arreglos, aquí es donde Parcelable es más poderoso que Serializable.

Resumido como sigue:

  1. Comparado con serializable, Parcelable tarda más en implementarlo, es decir, escribe más código
  2. Serializable es más fácil de implementar (no hay ningún método para copiar en la interfaz)
  3. Serializable utiliza la reflexión de Java para crear una gran cantidad de objetos temporales durante la sesión de transmisión, lo que provoca un GC considerable
  4. En Android, puede pasar la matriz Parcelable a través de Intent
  5. En Parcelable podemos escribir código personalizado, por lo que creará menos objetos basura, pero también debido a esta implementación personalizada, es más rápido que serializable y tiene mejor rendimiento.

Supongo que te gusta

Origin blog.csdn.net/Xia_Leon/article/details/83278452
Recomendado
Clasificación