encuentro que Parcelable se usa con mayor frecuencia en Android dentro de los datos Bu ndles, pero más específicamente dentro de un Handler que está enviando y recibiendo mensajes. Como ejemplo, puede tener un AsyncTask
o un Runnable
que debe ejecutarse en segundo plano pero publicar los datos resultantes en el hilo principal o Activity
.
Aquí hay un ejemplo simple. Si tengo un Runnable
que tiene este aspecto:
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 se puede ver, este ejecutable recibe un gestor en su constructor. Esto se llama desde algún Activity
así:
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 se define una clase como Parcelable
. Elegí una clase bastante compleja para mostrar porque hay algunas cosas que no verías con una simple.Aquí es la clase ProductInfo
, que paquetes y 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, ya que es el constructor resultante de tomar un paquete. 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.
que acaba de guardar mi día. GRACIAS. – Matthias
Simplemente no intente esto con Bitmaps dentro de su paquete (capaz) :( –
setDataPosition (0) me salvó! Gracias;) –