usar serializar putparcelable pasar online obtener objetos objeto entre como actividades android parcel

serializar - ¿Cómo usar Parcel en Android?



putparcelable android (5)

Parcelable utilizar Parcel para escribir y luego volver a leer un Parcelable . Por alguna razón, cuando leo el objeto desde el archivo, vuelve como null .

public void testFoo() { final Foo orig = new Foo("blah blah"); // Wrote orig to a parcel and then byte array final Parcel p1 = Parcel.obtain(); p1.writeValue(orig); final byte[] bytes = p1.marshall(); // Check to make sure that the byte array seems to contain a Parcelable assertEquals(4, bytes[0]); // Parcel.VAL_PARCELABLE // Unmarshall a Foo from that byte array final Parcel p2 = Parcel.obtain(); p2.unmarshall(bytes, 0, bytes.length); final Foo result = (Foo) p2.readValue(Foo.class.getClassLoader()); assertNotNull(result); // FAIL assertEquals( orig.str, result.str ); } protected static class Foo implements Parcelable { protected static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>() { public Foo createFromParcel(Parcel source) { final Foo f = new Foo(); f.str = (String) source.readValue(Foo.class.getClassLoader()); return f; } public Foo[] newArray(int size) { throw new UnsupportedOperationException(); } }; public String str; public Foo() { } public Foo( String s ) { str = s; } public int describeContents() { return 0; } public void writeToParcel(Parcel dest, int ignored) { dest.writeValue(str); } }

¿Qué me estoy perdiendo?

ACTUALIZACIÓN: para simplificar la prueba, he eliminado la lectura y escritura de archivos en mi ejemplo original.


¡Tener cuidado! No use Parcel para la serialización en un archivo

El paquete no es un mecanismo de serialización de propósito general. Esta clase (y la correspondiente API Parcelable para colocar objetos arbitrarios en una Parcela) está diseñada como un transporte de IPC de alto rendimiento. Como tal, no es apropiado colocar ningún paquete de datos en el almacenamiento persistente: los cambios en la implementación subyacente de cualquiera de los datos en el paquete pueden hacer que los datos anteriores sean ilegibles.

de http://developer.android.com/reference/android/os/Parcel.html


Ah, finalmente encontré el problema. Hubo dos de hecho.

  1. CREATOR debe ser público, no estar protegido. Pero mas importante,
  2. Debe llamar a setDataPosition(0) después de desasignar sus datos.

Aquí está el código de trabajo revisado:

public void testFoo() { final Foo orig = new Foo("blah blah"); final Parcel p1 = Parcel.obtain(); final Parcel p2 = Parcel.obtain(); final byte[] bytes; final Foo result; try { p1.writeValue(orig); bytes = p1.marshall(); // Check to make sure that the byte stream seems to contain a Parcelable assertEquals(4, bytes[0]); // Parcel.VAL_PARCELABLE p2.unmarshall(bytes, 0, bytes.length); p2.setDataPosition(0); result = (Foo) p2.readValue(Foo.class.getClassLoader()); } finally { p1.recycle(); p2.recycle(); } assertNotNull(result); assertEquals( orig.str, result.str ); } protected static class Foo implements Parcelable { public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>() { public Foo createFromParcel(Parcel source) { final Foo f = new Foo(); f.str = (String) source.readValue(Foo.class.getClassLoader()); return f; } public Foo[] newArray(int size) { throw new UnsupportedOperationException(); } }; public String str; public Foo() { } public Foo( String s ) { str = s; } public int describeContents() { return 0; } public void writeToParcel(Parcel dest, int ignored) { dest.writeValue(str); } }


Encuentro que Parcelable se usa con mayor frecuencia en Android dentro de paquetes de datos, pero más específicamente dentro de un controlador que envía y recibe mensajes. Como ejemplo, es posible que tenga una AsyncTask o Runnable que necesite ejecutarse en segundo plano, pero publique los datos resultantes en la cadena o Activity .

Aquí hay un ejemplo simple. Si tengo un Runnable que se ve así:

package com.example; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import com.example.data.ProductInfo; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.squareup.okhttp.OkHttpClient; public class AsyncRunnableExample extends Thread { public static final String KEY = "AsyncRunnableExample_MSG_KEY"; private static final String TAG = AsyncRunnableExample.class.getSimpleName(); private static final TypeToken<ProductInfo> PRODUCTINFO = new TypeToken<ProductInfo>() { }; private static final Gson GSON = new Gson(); private String productCode; OkHttpClient client; Handler handler; public AsyncRunnableExample(Handler handler, String productCode) { this.handler = handler; this.productCode = productCode; client = new OkHttpClient(); } @Override public void run() { String url = "http://someserver/api/" + productCode; try { HttpURLConnection connection = client.open(new URL(url)); InputStream is = connection.getInputStream(); InputStreamReader isr = new InputStreamReader(is); // Deserialize HTTP response to concrete type. ProductInfo info = GSON.fromJson(isr, PRODUCTINFO.getType()); Message msg = new Message(); Bundle b = new Bundle(); b.putParcelable(KEY, info); msg.setData(b); handler.sendMessage(msg); } catch (Exception err) { Log.e(TAG, err.toString()); } } }

Como puede ver, este ejecutable toma un controlador en su constructor. Esto se llama de alguna Activity como esta:

static class MyInnerHandler extends Handler{ WeakReference<MainActivity> mActivity; MyInnerHandler(MainActivity activity) { mActivity = new WeakReference<MainActivity>(activity); } @Override public void handleMessage(Message msg) { MainActivity theActivity = mActivity.get(); ProductInfo info = (ProductInfo) msg.getData().getParcelable(AsyncRunnableExample.KEY); // use the data from the Parcelable ''ProductInfo'' class here } } } private MyInnerHandler myHandler = new MyInnerHandler(this); @Override public void onClick(View v) { AsyncRunnableExample thread = new AsyncRunnableExample(myHandler, barcode.getText().toString()); thread.start(); }

Ahora, todo lo que queda es el corazón de esta pregunta, cómo defines una clase como Parcelable . Elegí una clase bastante compleja para mostrar porque hay algunas cosas que no verías con una simple. Aquí está la clase ProductInfo , que Parcels and unParcels limpiamente:

public class ProductInfo implements Parcelable { private String brand; private Long id; private String name; private String description; private String slug; private String layout; private String large_image_url; private String render_image_url; private String small_image_url; private Double price; private String public_url; private ArrayList<ImageGroup> images; private ArrayList<ProductInfo> related; private Double saleprice; private String sizes; private String colours; private String header; private String footer; private Long productcode; // getters and setters omitted here @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(id); dest.writeString(name); dest.writeString(description); dest.writeString(slug); dest.writeString(layout); dest.writeString(large_image_url); dest.writeString(render_image_url); dest.writeString(small_image_url); dest.writeDouble(price); dest.writeString(public_url); dest.writeParcelableArray((ImageGroup[])images.toArray(), flags); dest.writeParcelableArray((ProductInfo[])related.toArray(), flags); dest.writeDouble(saleprice); dest.writeString(sizes); dest.writeString(colours); dest.writeString(header); dest.writeString(footer); dest.writeLong(productcode); } public ProductInfo(Parcel in) { id = in.readLong(); name = in.readString(); description = in.readString(); slug = in.readString(); layout = in.readString(); large_image_url = in.readString(); render_image_url = in.readString(); small_image_url = in.readString(); price = in.readDouble(); public_url = in.readString(); images = in.readArrayList(ImageGroup.class.getClassLoader()); related = in.readArrayList(ProductInfo.class.getClassLoader()); saleprice = in.readDouble(); sizes = in.readString(); colours = in.readString(); header = in.readString(); footer = in.readString(); productcode = in.readLong(); } public static final Parcelable.Creator<ProductInfo> CREATOR = new Parcelable.Creator<ProductInfo>() { public ProductInfo createFromParcel(Parcel in) { return new ProductInfo(in); } public ProductInfo[] newArray(int size) { return new ProductInfo[size]; } }; @Override public int describeContents() { return 0; } }

El CREATOR es crítico, al igual que el constructor resultante que toma una Parcela. Incluí los tipos de datos más complejos para que pueda ver cómo Parcel y unParcel Arrays de objetos Parcelable. Esto es algo común cuando se usa Gson para convertir JSON en objetos con niños como en este ejemplo.



Yo también tuve un problema similar. solo el siguiente fragmento de emmby y esto me ayudó.

public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>() { public Foo createFromParcel(Parcel source) { final Foo f = new Foo(); f.str = (String) source.readValue(Foo.class.getClassLoader()); return f; } public Foo[] newArray(int size) { throw new UnsupportedOperationException(); }

Debe mantenerse en cada una de las clases que implementa Parcelable