Using Parcelable to Pass Highly Nested Classes Between Activities

Suppose I want to store a custom object of type MyObject

in Intent

. The way to do this is to make an MyObject

implementation Parcelable

. If one of the fields is MyObject

also a custom type object Widget

, then it's obvious what to do to Widget

implement Parcelable

too.

The problem is that Parcelable

there are a lot of templates to implement . You can work around this by not creating an Widget

implementation Parcelable

, but simply providing it with a constructor with Parcel

and a method writeToParcel

like this:

public final class Widget {

    private final int a;
    private final String b;

    Widget(Parcel in) {
        a = in.readInt();
        b = in.readString();
    }

    void writeToParcel(Parcel out) {
        out.writeInt(a);
        out.writeString(b);
    }
}

      

Then you can have a field Widget

in the object Parcelable

like this:

public class MyObject implements Parcelable {

    private final int x;
    private final Widget w;

    MyObject(int x, Widget w) {
        this.x = x;
        this.w = w;
    }

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

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(x);
        w.writeToParcel(out);
    }

    public static final Parcelable.Creator<MyObject> CREATOR
            = new Parcelable.Creator<MyObject>() {
        @Override
        public MyObject createFromParcel(Parcel in) {
            return new MyObject(in.readInt(), new Widget(in));
        }
        @Override
        public MyObject[] newArray(int size) {
            return new MyObject[size];
        }
    };
}

      

Is this an acceptable approach? Is it uniomatic android to have many custom classes in the project that can be written and read from Parcel

without actually embedding them Parcelable

? Or the fact that I am using Parcelable

to pass complex objects with many fields of custom types (which in turn have many fields of custom type, etc. etc.) indicate that I should not use Parcelable

in the first place ?

+3


source to share


3 answers


I would (and did) go with Parceler: https://github.com/johncarl81/parceler

Parceler is a code generation library that generates Android source code. You no longer need to do the Parcelable interface, writeToParcel () or createFromParcel (), or the public static final CREATOR. You just comment out the POJO with @Parcel and Parceler does the rest.



It is very easy to use.

+2


source


Recommended Parcelable

when working with passing custom objects through intents in Android. No "easy" job. Since you are only dealing with one additional layer of custom object (widget), I would recommend that you do as well Widget

Parcelable

. You can also check this link to see why this is a better approach than using the default serialization. https://coderwall.com/p/vfbing/passing-objects-between-activities-in-android



0


source


If your classes are beans the best solution is the accepted one. If not, I found that you can (slightly) reduce the pain of implementation Parcelable

by creating abstract classes ParcelablePlus

and CreatorPlus

as follows.

ParcelablePlus

:

abstract class ParcelablePlus implements Parcelable {

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

      

CreatorPlus

:

abstract class CreatorPlus<T extends Parcelable> implements Parcelable.Creator<T> {

    private final Class<T> clazz;

    CreatorPlus(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    @SuppressWarnings("unchecked")
    public final T[] newArray(int size) {
        // Safe as long as T is not a generic type.
        return (T[]) Array.newInstance(clazz, size);
    }
}

      

Then the class Widget

becomes:

public final class Widget extends ParcelablePlus {

    private final int a;
    private final String b;

    Widget(int a, String b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(a);
        out.writeString(b);
    }

    public static final Creator<Widget> CREATOR = new CreatorPlus<Widget>(Widget.class) {
        @Override
        public Widget createFromParcel(Parcel in) {
            return new Widget(in.readInt(), in.readString());
        }
    };
}

      

0


source







All Articles