GithubHelp home page GithubHelp logo

johncarl81 / parceler Goto Github PK

View Code? Open in Web Editor NEW
3.6K 72.0 271.0 1.53 MB

:package: Android Parcelables made easy through code generation.

Home Page: http://parceler.org

License: Apache License 2.0

Java 100.00%
java android android-parcelable boilerplate annotation-processor

parceler's Introduction

Parceler

parceler Build Status Maven Central

Have a question? Ask it on StackOverflow.

Found an issue? Please report it.

In Android, Parcelables are a great way to serialize Java Objects between Contexts. Compared with traditional Serialization, Parcelables take on the order of 10x less time to both serialize and deserialize. There is a major flaw with Parcelables, however. Parcelables contain a ton of boilerplate code. To implement a Parcelable, you must mirror the writeToParcel() and createFromParcel() methods such that they read and write to the Parcel in the same order. Also, a Parcelable must define a public static final Parcelable.Creator CREATOR in order for the Android infrastructure to be able to leverage the serialization code.

Parceler is a code generation library that generates the Android Parcelable boilerplate source code. No longer do you have to implement the Parcelable interface, the writeToParcel() or createFromParcel() or the public static final CREATOR. You simply annotate a POJO with @Parcel and Parceler does the rest. Because Parceler uses the Java JSR-269 Annotation Processor, there is no need to run a tool manually to generate the Parcelable code. Just annotate your Java Bean, compile and you are finished. By default, Parceler will serialize the fields of your instance directly:

@Parcel
public class Example {
    String name;
    int age;

    public Example() {}

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

    public String getName() { return name; }

    public int getAge() { return age; }
}

Be careful not to use private fields when using the default field serialization strategy as it will incur a performance penalty due to reflection.

To use the generated code, you may reference the generated class directly, or via the Parcels utility class:

Parcelable wrapped = Parcels.wrap(new Example("Andy", 42));

To dereference the @Parcel, just call the Parcels.unwrap() method:

Example example = Parcels.unwrap(wrapped);
example.getName(); // Andy
example.getAge(); // 42

Of course, the wrapped Parcelable can be added to an Android Bundle to transfer from Activity to Activity:

Bundle bundle = new Bundle();
bundle.putParcelable("example", Parcels.wrap(example));

And dereferenced in the onCreate() method:

Example example = Parcels.unwrap(getIntent().getParcelableExtra("example"));

This wrapping and unwrapping technique plays well with the Intent Factory pattern. In addition, Parceler is supported by the following libraries:

  • Transfuse - Allows @Parcel annotated beans to be used with the @Extra injection.

  • FragmentArgs - Uses the ParcelerArgsBundler adapter to wrap and unwrap @Parcel annotated beans with fragment parameters.

  • Dart - Autodetects @Parcel annotated beans and automatically unwraps them when using @InjectExtra.

  • AndroidAnnotations - Autodetects @Parcel annotated beans and automatically wraps/unwraps them when using @Extra, @FragmentArg, @InstanceState and other Bundle related annotations.

  • ActivityStarter - Supports natively Parceler objects as arguments to Activities, Fragments, Services, etc.

  • Remoter - Supports natively Parceler objects as arguments in @Remoter interfaces.

Parcel attribute types

Only a select number of types may be used as attributes of a @Parcel class. The following list includes the mapped types:

  • byte

  • double

  • float

  • int

  • long

  • char

  • boolean

  • String

  • IBinder

  • Bundle

  • SparseArray of any of the mapped types*

  • SparseBooleanArray

  • ObservableField

  • List, ArrayList and LinkedList of any of the mapped types*

  • Map, HashMap, LinkedHashMap, SortedMap, and TreeMap of any of the mapped types*

  • Set, HashSet, SortedSet, TreeSet, LinkedHashSet of any of the mapped types*

  • Parcelable

  • Serializable

  • Array of any of the mapped types

  • Any other class annotated with @Parcel

*Parcel will error if the generic parameter is not mapped.

Parceler also supports any of the above types directly. This is especially useful when dealing with collections of classes annotated with @Parcel:

Parcelable listParcelable = Parcels.wrap(new ArrayList<Example>());
Parcelable mapParcelable = Parcels.wrap(new HashMap<String, Example>());

Polymorphism

Note that Parceler does not unwrap inheritance hierarchies, so any polymorphic fields will be unwrapped as instances of the base class. This is because Parceler opts for performance rather than checking .getClass() for every piece of data.

@Parcel
public class Example {
    public Parent p;
    @ParcelConstructor Example(Parent p) { this.p = p; }
}

@Parcel public class Parent {}
@Parcel public class Child extends Parent {}
Example example = new Example(new Child());
System.out.println("%b", example.p instanceof Child); // true
example = Parcels.unwrap(Parcels.wrap(example));
System.out.println("%b", example.p instanceof Child); // false

Refer to the Custom Serialization section for an example of working with polymorphic fields.

Serialization techniques

Parceler offers several choices for how to serialize and deserialize an object in addition to the field-based serialization seen above.

Getter/setter serialization

Parceler may be configured to serialize using getter and setter methods and a non-empty constructor. In addition, fields, methods and constructor parameters may be associated using the @ParcelProperty annotation. This supports a number of bean strategies including immutability and traditional getter/setter beans.

To configure default method serialization, simply configure the @Parcel annotation with Serialization.BEAN:

@Parcel(Serialization.BEAN)
public class Example {
    private String name;
    private int age;
    private boolean enabled;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

    public boolean isEnabled() { return enabled; }
    public void setEnabled(boolean enabled) { this.enabled = enabled; }
}

To use a constructor with serialization, annotate the desired constructor with the @ParcelConstructor annotation:

@Parcel(Serialization.BEAN)
public class Example {
    private final String name;
    private final int age;
    private boolean enabled;

    @ParcelConstructor
    public Example(int age, String name, boolean enabled) {
        this.age = age;
        this.name = name;
        this.enabled = enabled;
    }

    public String getName() { return name; }

    public int getAge() { return age; }

    public boolean isEnabled() { return enabled; }
}

If an empty constructor is present, Parceler will use that constructor unless another constructor is annotated.

Mixing getters/setters and fields

You may also mix and match serialization techniques using the @ParcelProperty annotation. In the following example, firstName and lastName are written to the bean using the constructor while firstName is read from the bean using the field and lastName is read using the getLastName() method. The parameters firstName and lastName are coordinated by the parameter names "first" and "last" respectfully.

@Parcel
public class Example {
    @ParcelProperty("first")
    String firstName;
    String lastName;

    @ParcelConstructor
    public Example(@ParcelProperty("first") String firstName, @ParcelProperty("last") String lastName){
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() { return firstName; }

    @ParcelProperty("last")
    public String getLastName() { return lastName; }
}

For attributes that should not be serialized with Parceler, the attribute field, getter or setter may be annotated by @Transient.

Parceler supports many different styles centering around the POJO. This allows @Parcel annotated classes to be used with other POJO based libraries, including the following:

Static Factory support

As an alternative to using a constructor directly, Parceler supports using an annotated Static Factory to build an instance of the given class. This style supports Google’s AutoValue annotation processor / code generation library for generating immutable beans. Parceler interfaces with AutoValue via the @ParcelFactory annotation, which maps a static factory method into the annotated @Parcel serialization:

@AutoValue
@Parcel
public abstract class AutoValueParcel {

    @ParcelProperty("value") public abstract String value();

    @ParcelFactory
    public static AutoValueParcel create(String value) {
        return new AutoValue_AutoValueParcel(value);
    }
}

AutoValue generates a different class than the annotated @Parcel, therefore, you need to specify which class Parceler should build in the Parcels utility class:

Parcelable wrappedAutoValue = Parcels.wrap(AutoValueParcel.class, AutoValueParcel.create("example"));

And to deserialize:

AutoValueParcel autoValueParcel = Parcels.unwrap(wrappedAutoValue);

Custom serialization

@Parcel includes an optional parameter to include a manual serializer ParcelConverter for the case where special serialization is necessary. This provides a still cleaner option for using Parcelable classes than implementing them by hand.

The following code demonstrates using a ParcelConverter to unwrap the inheritance hierarchy during deserialization.

@Parcel
public class Item {
    @ParcelPropertyConverter(ItemListParcelConverter.class)
    public List<Item> itemList;
}
@Parcel public class SubItem1 extends Item {}
@Parcel public class SubItem2 extends Item {}

public class ItemListParcelConverter implements ParcelConverter<List<Item>> {
    @Override
    public void toParcel(List<Item> input, Parcel parcel) {
        if (input == null) {
            parcel.writeInt(-1);
        }
        else {
            parcel.writeInt(input.size());
            for (Item item : input) {
                parcel.writeParcelable(Parcels.wrap(item), 0);
            }
        }
    }

    @Override
    public List<Item> fromParcel(Parcel parcel) {
        int size = parcel.readInt();
        if (size < 0) return null;
        List<Item> items = new ArrayList<Item>();
        for (int i = 0; i < size; ++i) {
            items.add((Item) Parcels.unwrap(parcel.readParcelable(Item.class.getClassLoader())));
        }
        return items;
    }
}

Parceler is also packaged with a series of base classes to make Collection conversion easier located under the org.parceler.converter package of the api. These base classes take care of a variety of difficult or verbose jobs dealing with Collections including null checks and collectin iteration. For instance, the above ParcelConverter could be written using the `ArrayListParcelConverter':

public class ItemListParcelConverter extends ArrayListParcelConverter<Item> {
    @Override
    public void itemToParcel(Item item, Parcel parcel) {
        parcel.writeParcelable(Parcels.wrap(item), 0);
    }

    @Override
    public Item itemFromParcel(Parcel parcel) {
        return Parcels.unwrap(parcel.readParcelable(Item.class.getClassLoader()));
    }
}

Classes without Java source

For classes whose corresponding Java source is not available, one may include the class as a Parcel by using the @ParcelClass annotation. This annotation may be declared anywhere in the compiled source that is convenient. For instance, one could include the @ParcelClass along with the Android Application:

@ParcelClass(LibraryParcel.class)
public class AndroidApplication extends Application{
    //...
}

Multiple @ParcelClass annotations may be declared using the @ParcelClasses annotation.

In addition, classes referenced by @ParcelClass may be configured using the @Parcel annotation. This allows the serialization configuration through any parameter available on the @Parcel annotation including the serialization technique or classes to analyze.

One useful technique is the ability to define global custom converters for a type:

@ParcelClass(
    value = LibraryParcel.class,
    annotation = @Parcel(converter = LibraryParcelConverter.class))
class SomeClass{}

This allows for fine grained control over a class that isn’t available for direct modification.

Advanced configuration

Skipping analysis

It is a common practice for some libraries to require a bean to extend a base class. Although it is not the most optimal case, Parceler supports this practice by allowing the configuration of what classes in the inheritance hierarchy to analyze via the analyze parameter:

@Parcel(analyze = {One.class, Three.class})
class One extends Two {}
class Two extends Three {}
class Three extends BaseClass {}

In this example, only fields of the One and Three classes will be serialized, avoiding both the BaseClass and Two class parameters.

Specific wrapping

The Parcels utility class looks up the given class for wrapping by class. For performance reasons this ignores inheritance, both super and base classes. There are two solutions to this problem. First, one may specify additional types to associate to the given type via the implementations parameter:

class ExampleProxy extends Example {}
@Parcel(implementations = {ExampleProxy.class})
class Example {}

ExampleProxy proxy = new ExampleProxy();
Parcels.wrap(proxy);  // ExampleProxy will be serialized as a Example

Second, one may also specify the class type when using the Parcels.wrap() method:

ExampleProxy proxy = new ExampleProxy();
Parcels.wrap(Example.class, proxy);

Configuring Proguard

To configure Proguard, add the following lines to your proguard configuration file. These will keep files related to the Parcels utilty class and the Parcelable CREATOR instance: er

# Parceler library
-keep interface org.parceler.Parcel
-keep @org.parceler.Parcel class * { *; }
-keep class **$$Parcelable { *; }

Getting Parceler

You may download Parceler as a Maven dependency:

<dependency>
    <groupId>org.parceler</groupId>
    <artifactId>parceler</artifactId>
    <version>1.1.12</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.parceler</groupId>
    <artifactId>parceler-api</artifactId>
    <version>1.1.12</version>
</dependency>

or Gradle:

implementation 'org.parceler:parceler-api:1.1.12'
annotationProcessor 'org.parceler:parceler:1.1.12'

Or from Maven Central.

License

Copyright 2011-2015 John Ericksen

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

parceler's People

Contributors

ansman avatar bryant1410 avatar danielgunna avatar dbachelder avatar dependabot[bot] avatar ezet avatar friederbluemle avatar gitter-badger avatar gloix avatar hindupuravinash avatar jlleitschuh avatar johncarl81 avatar johnjohndoe avatar josesamuel avatar lfdversluis avatar loganj avatar marcinmoskala avatar naitbit avatar rhonyabdullah avatar sakuna63 avatar vinc3m1 avatar yuyakaido avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

parceler's Issues

cryptic error with inherited classes?

Could you make this error a bit more explanatory? :-)

   Execution failed for task ':app:compileDebugJava'.
   > org.androidtransfuse.TransfuseAnalysisException: @Parcel code generation did not complete successfully.

I got it trying to use it with an abstract class hierarchy...something like:

@Parcel
abstract class A {
  int field1;
  int field2;
}
@Parcel
class B extends A {
  String fields
  //etc.
}

And marked class B as @Parcel only initially since I wouldn't try parceling class A. I tried adding @Parcel to class A w/o luck.

It'd help if it printed out how far it got parceling so we could get a bit more of a clue as to what field or class it's having a hard time with :-P

It's probably also a good idea to add a hierarchy class as an example on the site too..

Don't require setters or empty constructor

It would be really nice if the library would be able to use the constructor method or simply set the fields. This would allow immutable objects and also make it closer to how Gson behaves.

No corresponding property found for constructor parameter nodes

I want to make my data immutable so this is what I did:

....
private final HashMap<String, Bundle> nodes;
....

@ParcelConstructor
 NavigationPath(HashMap<String, Bundle> nodes) {
    this.nodes = nodes;
}

 HashMap<String, Bundle> getNodes() {
    return nodes;
}

Notice that the constructor and getter for node is package private.

This exception is thrown when compiling:

NavigationPath.java:40: error: Parceler: No corresponding property found for constructor parameter     nodes
 NavigationPath(HashMap<String, Bundle> nodes) {

If I make the methods/constructors public, then I loose immutability.
Can you make parceler support at least package private visibility?
Butterknife does that without problems so I assume this can be done?

Add field name in warnings

In warnings like this:

warning: Parceler: Reflection is required to modify private final fields, consider using non-private.
warning: Parceler: Reflection is required to access private fields, consider using non-private.

Can we add the field name?
Something like this:

private int count;
private final int theAnswer = 42;
warning: Parceler: [on field "count"]Reflection is required to modify private fields, consider using non-private. 
warning: Parceler: [on field "theAnswer"]Reflection is required to access private final fields, consider using non-private.

Because my external library has hundreds of final/static fields and finding them all is taking forever.

Compile error: cannot find symbol parcel$$3 .writeParcelable(model$$2 .field, flags);

I'm testing parceler library. Thanks for great works.

But I got compiler error when I used Parcelable object in 2nd depth.

Here's the my code.

@Parcel
public class TestModel {
    public static transient final int DUMP = 1010;

    int i;
    boolean b;
    long l;

    TestSubModel subModel;

    public static class TestParcelable implements Parcelable {

        int i;

        public TestParcelable() {

        }

        public TestParcelable(android.os.Parcel source) {
            i = source.readInt();
        }

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

        @Override
        public void writeToParcel(android.os.Parcel dest, int flags) {
            dest.writeInt(i);
        }

        public static final Parcelable.Creator<TestParcelable> CREATOR = new Parcelable.Creator<TestParcelable>() {

            @Override
            public TestParcelable createFromParcel(android.os.Parcel source) {
                return new TestParcelable(source);
            }

            @Override
            public TestParcelable[] newArray(int size) {
                return new TestParcelable[size];
            }
        };

    }

    @Parcel
    public static class TestSubModel {
        TestParcelable testParcelable;
    }

    public TestModel() {
    }

    public TestModel(int i) {
        this.i = i;
    }
}

Here's the output from gradle.

TestModel$$Parcelable.java:58: error: cannot find symbol
        parcel$$3 .writeParcelable(testSubModel$$2 .testParcelable, flags);
                                                                    ^
  symbol:   variable flags
  location: class TestModel$$Parcelable
1 error

List of @Parcel

serialize and deserialize @Parcel annotated classes using the appropriate Parcelable representation via either Parcels.get(example) or direct instantiation: new Example$$Parcelable(example).

Compiler warns about private static fields requiring reflection.

i.e:

Parceler: Reflection is required to modify private final fields, consider using non-private.
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");

I could be wrong about this, but I'm not sure static fields would need to be touched when parceling up objects?

In my case, I could just make them public I guess, since they're final as well (they're constants).

Class not found when unmarshalling: org.parceler.NonParcelRepository$MapParcelable

Got a strange case here:
I'm trying to save a HashMap<String, String in a Bundle along with some other stuff...

Bundle bundle = new Bundle();
HashMap<String, String> map = new HashMap<>();
map.put("a", "b");
bundle.putParcelable("foo", Parcels.wrap(map));
bundle.putInt("foo1", 42);
// and putting many other stuff

The bundle then gets put into another map:

HashMap<String, Bundle> nodes = new HashMap<>();
nodes.put("bar", bundle);
// and putting  many more bundles...

nodes is part of a data object structured like this:

@Parcel
public class MyData {
    HashMap<String, Bundle> nodes = new HashMap<>();
}

an instance of MyData gets saved into Bundle :

myBundle.putParcelable("baz", Parcels.wrap(myData));

the myBundle gets passed around in Activities and Fragments.....

at some point in time, I would retrieve some of the values in myBundle, and it's working for the stuff that isn't wrapped in a Parcel.wrap()

MyData data = Parcels.unwrap( myBundle.getParcelable(baz));
Bundle bundle data.nodes.get("bar");
HashMap<String, String> map = Parcels.unwrap(bundle.getParcelable("foo")); // fails 
int myInt = bundle.getInt("foo1"); // works

Here's the stacktrace

    java.lang.ClassNotFoundException: org.parceler.NonParcelRepository$MapParcelable
            at java.lang.Class.classForName(Native Method)
            at java.lang.Class.forName(Class.java:305)
            at java.lang.Class.forName(Class.java:269)
            at android.os.Parcel.readParcelableCreator(Parcel.java:2133)
            at android.os.Parcel.readParcelable(Parcel.java:2097)
            at android.os.Parcel.readValue(Parcel.java:2013)
            at android.os.Parcel.readArrayMapInternal(Parcel.java:2314)
            at android.os.Bundle.unparcel(Bundle.java:249)
            at android.os.Bundle.getParcelable(Bundle.java:1206)
            // getParcelable()'s calling class is here
            // ........
         Caused by: java.lang.ClassNotFoundException: Didn't find class     "org.parceler.NonParcelRepository$MapParcelable" on path: DexPathList[[directory     "."],nativeLibraryDirectories=[/system/lib]]

            at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:469
            at java.lang.Class.classForName(Native Method)
            at java.lang.Class.forName(Class.java:305)
            at java.lang.Class.forName(Class.java:269)
            at android.os.Parcel.readParcelableCreator(Parcel.java:2133)
            at android.os.Parcel.readParcelable(Parcel.java:2097)
            at android.os.Parcel.readValue(Parcel.java:2013)
            at android.os.Parcel.readArrayMapInternal(Parcel.java:2314)
            at android.os.Bundle.unparcel(Bundle.java:249)
            at android.os.Bundle.getParcelable(Bundle.java:1206)
            // .......
     Suppressed: java.lang.ClassNotFoundException: org.parceler.NonParcelRepository$MapParcelable
            at java.lang.Class.classForName(Native Method)
            at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
            at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
            ... 29 more
         Caused by: java.lang.NoClassDefFoundError: Class "Lorg/parceler/NonParcelRepository$MapParcelable;" not found
            ... 33 more

This whole thing reminds me of not setting the ClassLoader for a Parcelable object, which causes strange crashes before I started using Parceler

Gradle and Parceler causing "Unable to create ParcelableFactory"?

I've set up build.gradle according to the example. Everything compiles fine but when I run the app an invoke Parcels.wrap, the app crashes. The project is set up with android-apt plugin and AndroidAnnotations which both are working fine.

org.parceler.ParcelerRuntimeException: Unable to create ParcelableFactory for sg.ruqqq.test.Item
E/AndroidRuntime(30134):    at org.parceler.Parcels$ParcelCodeRepository.get(Parcels.java:182)
E/AndroidRuntime(30134):    at org.parceler.Parcels.wrap(Parcels.java:69)

Any help?

org.parceler.ParcelerRuntimeException: Unable to create ParcelableFactory for java.util.Collections$UnmodifiableRandomAccessList

I'm not sure whether this is intentional or not but I'll report it anyway :)

Basically, anything that is not an ArrayList would get exceptions like this, for example, stuff returned from:

Collections.unmodifiableList()
ArrayList.subList(start, end)

Just to name a few....

Even though the returned value still implements List...

In README.md, List wast part of the supported types

This problem can be easily solved by wrapping the List with ArrayList's copy constructor.

Errors with arrays as constructor parameters

In the latest release (and maybe earlier releases) the is some kind of problem with using arrays as constructor parameters.

For instance, this test fails unexpectedly (both the array and the integer values become garbage):

@RunWith(RobolectricTestRunner.class)
public class ArrayTest {

    @Test
    public void testIntArray() {
        IntArrayClass prewrap = new IntArrayClass();
        prewrap.setI(10);
        prewrap.setArr(new int[] { 1,2,3,4,5 });

        IntArrayClass unwrapped = Parcels.unwrap(ParcelsTestUtil.wrap(prewrap));

        assertEquals(10, unwrapped.i);
        assertArrayEquals(new int[]{1, 2, 3, 4, 5}, unwrapped.getArr());
    }

    @Parcel(Parcel.Serialization.METHOD)
    public static class IntArrayClass {

        int[] arr;
        int i;

        @ParcelConstructor
        public IntArrayClass(int i, int[] arr) {
            this.arr = arr;
            this.i = i;
        }

        public IntArrayClass() {}

        public int[] getArr() { return arr; } 
        public void setArr(int[] arr) { this.arr = arr; }
        public int getI() { return i; }
        public void setI(int i) { this.i = i; }
    }
}

If I remove the array, or comment out the constructor annotated with @ParcelConstructor, then the test passes as expected, so the issue seems to be with using arrays as constructor parameters.

The test also fails with ArrayList instead of a plain int array, so maybe this is a general problem with container types.

Problem with @ParcelClass annotations and related classes

I have these annotations

@ParcelClasses({
    @ParcelClass(A.class),
    @ParcelClass(B.class)
})

Where B has a List<A> member. I get this exception:

Exception in thread "pool-10-thread-1" org.parceler.ParcelerRuntimeException: Unable to find appropriate Parcel method to write A
    at org.parceler.internal.Generators.getGenerator(Generators.java:49)
    at org.parceler.internal.generator.ListReadWriteGenerator.generateReader(ListReadWriteGenerator.java:82)
    at org.parceler.internal.ParcelableGenerator.buildReadFromParcelExpression(ParcelableGenerator.java:223)
    at org.parceler.internal.ParcelableGenerator.buildReadFromParcel(ParcelableGenerator.java:191)
    at org.parceler.internal.ParcelableGenerator.generateParcelable(ParcelableGenerator.java:118)
    at org.parceler.internal.ExternalParcelTransactionWorker.innerRun(ExternalParcelTransactionWorker.java:63)
    at org.parceler.internal.ExternalParcelTransactionWorker.innerRun(ExternalParcelTransactionWorker.java:37)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
    at org.androidtransfuse.transaction.Transaction.run(Transaction.java:77)

Compatibility Issues with Project Lombok / hrisey

It seems that Parceler is currently not compatible with hrisey, a Android specific fork of Project Lombok.
I've set up my domain classes with @Data, @Value,@AllArgsConstructor, @NoArgsConstructor and @RequiredArgsConstructor.
When I try to launch the modified app, I get the following StackTrace:

Exception in thread "pool-54-thread-1" java.lang.NullPointerException
    at org.parceler.internal.ParcelableGenerator.buildParcelRead(ParcelableGenerator.java:148)
    at org.parceler.internal.generator.ParcelReadWriteGenerator.generateReader(ParcelReadWriteGenerator.java:54)
    at org.parceler.internal.ParcelableGenerator.buildReadFromParcelExpression(ParcelableGenerator.java:282)
    at org.parceler.internal.ParcelableGenerator.buildReadFromParcel(ParcelableGenerator.java:234)
    at org.parceler.internal.ParcelableGenerator.buildParcelRead(ParcelableGenerator.java:166)
    at org.parceler.internal.ParcelableGenerator.generateParcelable(ParcelableGenerator.java:100)
    at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:55)
    at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:35)
    at org.parceler.transfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.parceler.transfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
    at org.parceler.transfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.parceler.transfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
    at org.parceler.transfuse.transaction.Transaction.run(Transaction.java:77)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Access to CREATOR

How does one get an access to Creator object of a class annotated with @Parcel?

Stack trace/error readability

Would it be possible to log the class caused generation to fail to appear at the top of the stack trace or in the error message?

The current error message is:

Unable to find appropriate Parcel method to write java.lang.Object

I'd love to see

Unable to find appropriate Parcel method to write java.lang.Object in com.test.myclass

Here's the output from ./gradlew assembleDebug --stacktrace

FAILURE: Build failed with an exception.
              
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcelExpression(ParcelableGenerator.java:282)
* What went wrong:
Execution failed for task ':app:compileDebugJava'.
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcel(ParcelableGenerator.java:234)
        at org.parceler.internal.ParcelableGenerator.buildParcelRead(ParcelableGenerator.java:166)
> org.parceler.transfuse.TransfuseAnalysisException: @Parcel code generation did not complete successfully.
        at org.parceler.internal.generator.ParcelReadWriteGenerator.generateReader(ParcelReadWriteGenerator.java:63)
              
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcelExpression(ParcelableGenerator.java:282)
* Try:        
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcel(ParcelableGenerator.java:234)
        at org.parceler.internal.ParcelableGenerator.buildParcelRead(ParcelableGenerator.java:166)
Run with --info or --debug option to get more log output.
        at org.parceler.internal.ParcelableGenerator.generateParcelable(ParcelableGenerator.java:100)
        at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:54)
        at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:34)
        at org.parceler.transfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
        at org.parceler.transfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
        at org.parceler.transfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
        at org.parceler.transfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
              
        at org.parceler.transfuse.transaction.Transaction.run(Transaction.java:77)
* Exception is:
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:744)
Exception in thread "pool-9-thread-3" org.parceler.ParcelerRuntimeException: Unable to find appropriate Parcel method to write java.lang.Object
        at org.parceler.internal.Generators.getGenerator(Generators.java:49)
        at org.parceler.internal.generator.MapReadWriteGenerator.generateReader(MapReadWriteGenerator.java:90)
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcelExpression(ParcelableGenerator.java:282)
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcel(ParcelableGenerator.java:234)
        at org.parceler.internal.ParcelableGenerator.buildParcelRead(ParcelableGenerator.java:166)
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:compileDebugJava'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:289)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
        at org.parceler.internal.ParcelableGenerator.generateParcelable(ParcelableGenerator.java:100)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$1.run(DefaultTaskPlanExecutor.java:33)
        at org.gradle.internal.Factories$1.create(Factories.java:22)
        at org.gradle.cache.internal.DefaultCacheAccess.longRunningOperation(DefaultCacheAccess.java:198)
        at org.gradle.cache.internal.DefaultCacheAccess.longRunningOperation(DefaultCacheAccess.java:266)
        at org.gradle.cache.internal.DefaultPersistentDirectoryStore.longRunningOperation(DefaultPersistentDirectoryStore.java:135)
        at org.gradle.api.internal.changedetection.state.DefaultTaskArtifactStateCacheAccess.longRunningOperation(DefaultTaskArtifactStateCacheAccess.java:95)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:31)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:86)
        at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:29)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:61)
        at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
        at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:54)
        at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:67)
        at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:61)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:54)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:166)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:113)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:81)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:64)
        at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33)
        at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:35)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
        at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:50)
        at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:171)
        at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:201)
        at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:174)
        at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:34)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:170)
        at org.parceler.transfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
        at org.parceler.transfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
        at org.parceler.transfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:139)
        at org.parceler.transfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
        at org.parceler.transfuse.transaction.Transaction.run(Transaction.java:77)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:744)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
        at org.gradle.launcher.Main.doAction(Main.java:46)
Exception in thread "pool-9-thread-2" org.parceler.ParcelerRuntimeException: Unable to find appropriate Parcel method to write java.lang.Object
        at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
        at org.parceler.internal.Generators.getGenerator(Generators.java:49)
        at org.gradle.launcher.Main.main(Main.java:37)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:50)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:32)
        at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
        at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:30)
        at org.parceler.internal.generator.MapReadWriteGenerator.generateReader(MapReadWriteGenerator.java:90)
        at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:127)
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcelExpression(ParcelableGenerator.java:282)
        at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:55)
Caused by: java.lang.RuntimeException: org.parceler.transfuse.TransfuseAnalysisException: @Parcel code generation did not complete successfully.
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcel(ParcelableGenerator.java:234)
        at org.parceler.internal.ParcelableGenerator.buildParcelRead(ParcelableGenerator.java:166)
        at org.parceler.internal.generator.ParcelReadWriteGenerator.generateReader(ParcelReadWriteGenerator.java:63)
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcelExpression(ParcelableGenerator.java:282)
        at com.sun.tools.javac.main.Main.compile(Main.java:553)
        at org.parceler.internal.ParcelableGenerator.buildReadFromParcel(ParcelableGenerator.java:234)
        at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
        at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
        at org.gradle.api.internal.tasks.compile.jdk6.Jdk6JavaCompiler.execute(Jdk6JavaCompiler.java:45)
        at org.gradle.api.internal.tasks.compile.jdk6.Jdk6JavaCompiler.execute(Jdk6JavaCompiler.java:38)
        at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:96)
        at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:49)
        at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:35)
        at org.gradle.api.internal.tasks.compile.DelegatingJavaCompiler.execute(DelegatingJavaCompiler.java:29)
        at org.parceler.internal.ParcelableGenerator.buildParcelRead(ParcelableGenerator.java:166)
        at org.gradle.api.internal.tasks.compile.DelegatingJavaCompiler.execute(DelegatingJavaCompiler.java:20)
        at org.gradle.api.internal.tasks.compile.IncrementalJavaCompilerSupport.execute(IncrementalJavaCompilerSupport.java:33)
        at org.gradle.api.internal.tasks.compile.IncrementalJavaCompilerSupport.execute(IncrementalJavaCompilerSupport.java:24)
        at org.gradle.api.tasks.compile.Compile.compile(Compile.java:67)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:219)
        at org.parceler.internal.ParcelableGenerator.generateParcelable(ParcelableGenerator.java:100)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:212)
        at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:54)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:201)
        at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:34)
        at org.parceler.transfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
        at org.parceler.transfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:533)
        at org.parceler.transfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:516)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        ... 52 more
Caused by: org.parceler.transfuse.TransfuseAnalysisException: @Parcel code generation did not complete successfully.
        at org.parceler.internal.ParcelProcessor.checkForErrors(ParcelProcessor.java:82)
        at org.parceler.transfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
        at org.parceler.transfuse.transaction.Transaction.run(Transaction.java:77)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:744)
        at org.parceler.ParcelAnnotationProcessor.process(ParcelAnnotationProcessor.java:71)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$200(JavacProcessingEnvironment.java:91)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.runContributingProcs(JavacProcessingEnvironment.java:627)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1033)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1198)
        at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1173)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:859)
        at com.sun.tools.javac.main.Main.compile(Main.java:523)
        ... 72 more
           
              
BUILD FAILED  

Parcel.unwrap()

I just came across this library, it looks nice. I haven't used it yet, but from looking at the front page example:

    Example example = ((ParcelableWrapper<Example>)wrapped).getParcel();
    example.getName(); // Andy
    example.getAge(); // 42

The unsafe generic cast could be hidden away into a Parcel.unwrap() method. Something along these lines:

public final class Parcels {
  public static <T> Parcelable unwrap(Parcelable input) {
    ParcelableWrapper<T> wrapper = (ParcelableWrapper<T>) input;
    return wrapper.getParcel();
  }
}

Then the calling code would be more sexy:

    Example example = Parcels.unwrap(wrapped);
    example.getName(); // Andy
    example.getAge(); // 42

ClassNotFoundException: android.os.Parcel when using @ParcelClass

I got an external library(jar) that has an Apple:

public class Apple {
  // this is for example only
    public int count = 1024;
    public String name = "Macintosh";
    public int[] balls = { 12, 2, 3 };
}

I need to use the Apple in my Fragment:

@ParcelClass(Apple.class) // assume Apple properly imported
public class AppleFragment extends Fragment{
    //... 
    private Apple myApple;
    //... 
}

If I compile the app

gradle assembleDebug

the compiler complains:

//....
// everything before this is normal
:app:compileDebugJava
Exception in thread "pool-22-thread-1" java.lang.NoClassDefFoundError: android/os/Parcel
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
    at java.lang.Class.getDeclaredMethods(Class.java:1962)
    at org.androidtransfuse.adapter.classes.ASTClassFactory.buildType(ASTClassFactory.java:119)
    at org.androidtransfuse.adapter.classes.ASTClassFactory.getType(ASTClassFactory.java:72)
    at org.androidtransfuse.adapter.classes.ASTClassFactory.buildType(ASTClassFactory.java:109)
    at org.androidtransfuse.adapter.classes.ASTClassFactory.getType(ASTClassFactory.java:72)
    at org.androidtransfuse.adapter.classes.ASTClassFactory.getType(ASTClassFactory.java:63)
    at org.parceler.internal.ExternalParcelTransactionWorker.getConverterType(ExternalParcelTransactionWorker.java:78)
    at org.parceler.internal.ExternalParcelTransactionWorker.innerRun(ExternalParcelTransactionWorker.java:69)
    at org.parceler.internal.ExternalParcelTransactionWorker.innerRun(ExternalParcelTransactionWorker.java:36)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
    at org.androidtransfuse.transaction.Transaction.run(Transaction.java:77)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.ClassNotFoundException: android.os.Parcel
    at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 19 more
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
// everything after this is normal
:app:preDexDebug UP-TO-DATE
//....

Parceler is added like this in build.gradle

 provided 'org.parceler:parceler:0.2.9'
 compile 'org.parceler:parceler-api:0.2.9'

The Apple class is just an example, in reality it happens with any POJO/ simple class with a few string fields. And the strange thing is that the App works(I didn't test whether Parcel actually persists any data) without throwing any exception. The generated class is there and the content look good to me:
From Parceler$$Parcels.java

package org.parceler;

import java.util.HashMap;
import java.util.Map;
import somepackage.Apple;
import somepackage.Apple$$Parcelable;

@Generated(value = "org.parceler.ParcelAnnotationProcessor", date = "2014-05-31T01:33+0800")
public class Parceler$$Parcels
    implements Repository<org.parceler.Parcels.ParcelableFactory>
{

    private final Map<Class, org.parceler.Parcels.ParcelableFactory> map$$0 = new HashMap<Class, org.parceler.Parcels.ParcelableFactory>();

    public Parceler$$Parcels() {
        map$$0 .put(Apple.class, new Parceler$$Parcels.Apple$$Parcelable$$0());
    }

    public Map<Class, org.parceler.Parcels.ParcelableFactory> get() {
        return map$$0;
    }

    private final static class Apple$$Parcelable$$0
        implements org.parceler.Parcels.ParcelableFactory<Apple>
    {


        @Override
        public Apple$$Parcelable buildParcelable(Apple input) {
            return new Apple$$Parcelable(input);
        }

    }

}

I'm not so sure about Parceler$$Parcels$Apple$$Parcelable$$0.class though:

package org.parceler;

import somepackage.Apple;
import somepackage.Apple..Parcelable;

final class Parceler$$Parcels$Apple$$Parcelable$$0
  implements Parcels.ParcelableFactory<Apple>
{
  public Apple..Parcelable buildParcelable(Apple input)
  {
    return new Apple..Parcelable(input);
  }
}

I have a feeling that nothing is actually persisted....
Is there anything that I can do to fix this?

Annotation processor does not work with Android Gradle build

Unlike Maven, the Android Gradle build does not put the Android runtime on the annotation processor class path. During build the following exception occurs:

Exception in thread "pool-4-thread-1" java.lang.NoClassDefFoundError: android/os/IBinder
    at org.parceler.internal.ParcelableGenerator.setup(ParcelableGenerator.java:290)
    at org.parceler.internal.ParcelableGenerator.<init>(ParcelableGenerator.java:88)
    at org.androidtransfuse.transaction.Parceler$$TransactionWorker$$Provider$$0.get(Parceler$$TransactionWorker$$Provider$$0.java:61)
    at org.androidtransfuse.transaction.Parceler$$TransactionWorker$$Provider$$0.get(Parceler$$TransactionWorker$$Provider$$0.java:19)
    at org.androidtransfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:54)
    at org.androidtransfuse.transaction.Transaction.run(Transaction.java:77)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.ClassNotFoundException: android.os.IBinder
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 9 more

A similar issue was fixed in butterknife before
JakeWharton/butterknife#77, maybe this can give some guidance on how to fix it?

IncompatibleClassChangeError when building my transfuse project

I'm not yet using parceler in my project, but I am using transfuse and will eventually be using parceler... So I do have the parceler stuff in my tool chain, and I just started getting these exceptions... I have no problems building if I comment out the parceler deps..

I have no clue where the issue is occurring... there is no context for the error.

Caused by: java.lang.IncompatibleClassChangeError: Implementing class
    at org.parceler.ParcelAnnotationProcessor$$Bootstrap.inject(ParcelAnnotationProcessor$$Bootstrap.java:42)
    at org.parceler.ParcelAnnotationProcessor$$Bootstrap.inject(ParcelAnnotationProcessor$$Bootstrap.java:19)
    at org.parceler.ParcelAnnotationProcessor.init(ParcelAnnotationProcessor.java:57)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$ProcessorState.<init>(JavacProcessingEnvironment.java:517)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:614)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:707)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1700(JavacProcessingEnvironment.java:97)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1029)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1163)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1108)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:824)
    at com.sun.tools.javac.main.Main.compile(Main.java:439)

Field converter sample

Can you provide a sample on how to specify a field converter?

For instance, I have an entity which has, among other fields, a field of type org.joda.time.DateTime. How do I specify how to parcel/unparcel this field? Is it possible? I know about ParcelConverter but I don't want to specify how to parcel all my other fields.

Thanks for making this great library available to all.

StackOverflowError with @Parcel Enum

When I try to @Parcel an enum, I get a StackOverflowError.

Here is my test Parcelable class...

@Parcel
public class ParcelableClass {

    public String someString;
    public int someInt;
    public Type type;

    @Parcel
    public enum Type {
        TYPE_A,
        TYPE_B,
        TYPE_C
    }
}

Here is my parceling code where it blows up...

public class MyActivity extends Activity {
    ...
    @Override
    protected void onSaveInstanceState(Bundle outState) {

        ParcelableClass parcelableObject = new ParcelableClass();
        parcelableObject.someString = "test";
        parcelableObject.someInt = 5;
        parcelableObject.type = ParcelableClass.Type.TYPE_B;

        outState.putParcelable("keyParcelableClass", Parcels.wrap(parcelableObject));

        super.onSaveInstanceState(outState);
    }
    ...
}

And this is the stacktrace...

09-09 22:17:19.567  32393-32393/com.example.ahuang.helloworld E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.ahuang.helloworld, PID: 32393
java.lang.StackOverflowError
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:79)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahuang_helloworld_ParcelableClass$Type(ParcelableClass$$Parcelable.java:80)
        at com.example.ahuang.helloworld.ParcelableClass$$Parcelable.writecom_example_ahu

Note, when I don't set the parcelableObject.type = ParcelableClass.Type.TYPE_B;, it works fine; I'm able to unparcel it, and the type field is null.

I have the following in my build.gradle...

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile "org.parceler:parceler-api:0.2.12"
    provided "org.parceler:parceler:0.2.12"
}

ParcelableAnalysis#findFields includes static fields

I have a static field on a base class, and ParcelableAnalysis is complaining that it can't find a read/write generator for its type. Given that it's a static field and not an instance member, ParcelableAnalysis shouldn't even be trying. Looks like maybe this will require a transfuse fix.

Not sure if the other member finders exclude class members or not.

wrap fails for null Boolean feed

I have a Boolean field in my parcel which can sometimes be null...

the generated code fails with an NPE:

        parcel$$1 .writeBooleanArray(new boolean[] {InjectionUtil.getField(java.lang.Boolean.class, com.company.ValueObject.class, valueObject$$0, "isFeatured")});

how to build and run a helloworld project using parceler?

I'm interesting in using parceler in my android project. I've read the introduction and some of the issues, but I am still unable to setup a simple helloworld project to run. It seems that the problem is no annotation class is generated.
Can anybody write an entry level manual to show, step by step, how to setup a helloworld project using parceler, with the IDE eclipse or IntelliJ ?

Nested class not included in @ParcelClasses

Say I have a class that looks like this(In a library that I don't have control of):

public class Foo{
 public Bar[] bars;
 public static class Bar{
 //...
 }
}

If I annotate them using

@ParcelClass(Foo.class)

The compiler complains about not able to serialize Bar
If I do it like this:

@ParcelClasses({@ParcelClass(Foo.class), @ParcelClass(Foo.Bar.class)})

Everything works perfectly.
I am totally fine with the current way of doing it, but I thought an enhancement like auto detecting all the nested classes would be nice too.

PS:
From memory, I think we have to use CompoundReference or something like that....

Errors with inheritance and contructors

The support for inheritance that was added in 0.2.7 does not work very well with constructors.

For example, this causes an error:

@Parcel
public class AClass {
    String message;
    public final String getMessage() { return this.message; }
    public void setMessage(String message) { this.message = message; }

    public AClass(String message) {
        this.message = message;
    }
}

@Parcel
public class ASubClass extends AClass {
    int status;
    public int getStatus() { return status; }
    public void setStatus(int status) { this.status = status; }

    public ASubClass(String message, int status) {
        super(message);
        this.status = status;
    }
}

As far as I can tell, this i caused by the way the hierarchy loop works in ParcelableAnalysis. The loop starts at the subclass and collect it's fields and properties. Then it collect the constructor and attempts to validate the properties, but as the message property is defined by the parent, it cannot be validated at this state.

If the hierarchy loop were oriented the other way around, so that it started with the base class, then I think i would be easier to get this inheritance working.

Support List type

Currently java.util.List is supported by the framework, and I think it is a must for this to be a must for every android application.

I know that TypeErasure gets on the way, but maybe we can have some special approach.

External Configuration

Beans to be enhanced by the annotation processor may not exist in the current compile pass (ie: in an external library or from code generation). Therefore, we need a way to configure Parceler to find these classes.

The idea is to add an annotation that Parceler will recognize:

@ParcelClass(Example.class)

Since this annotation doesn't rely on the class that it annotates, this configuration can appear anywhere. Perhaps on the Application class or some other convenient configuration point:

@ParcelClass(Example.class)
public class SomeApplication extends Application{
//...
}

Incorrect warning for final fields

With a public static final String I see this warning:

Warning:(10, 30) Gradle: Parceler: Reflection is required to modify final field: String REQUEST_CODE, consider using non-private.

Is there any circumstance in which someone would want a static final field to be parceled? Or any static field, for that matter?

NullPointerException when building app with maven

Getting this when trying to build the app with Maven:

[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ app ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding MacRoman, i.e. build is platform dependent!
[INFO] Compiling 28 source files to /Users/[path]/android/app/target/classes
Exception in thread "pool-3-thread-1" java.lang.NullPointerException
    at com.sun.tools.javac.model.JavacElements.cast(JavacElements.java:627)
    at com.sun.tools.javac.model.JavacElements.getPackageOf(JavacElements.java:362)
    at org.androidtransfuse.adapter.element.ASTElementFactory.buildPackageClass(ASTElementFactory.java:130)
    at org.androidtransfuse.adapter.element.ASTElementFactory.buildType(ASTElementFactory.java:87)
    at org.androidtransfuse.adapter.element.ASTElementFactory.getType(ASTElementFactory.java:78)
    at org.parceler.internal.ReloadableASTElementFactory$ReloadableASTTypeProvider.get(ReloadableASTElementFactory.java:66)
    at org.parceler.internal.ReloadableASTElementFactory$ReloadableASTTypeProvider.get(ReloadableASTElementFactory.java:54)
    at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:52)
    at org.parceler.internal.ParcelTransactionWorker.innerRun(ParcelTransactionWorker.java:34)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
    at org.androidtransfuse.transaction.Transaction.run(Transaction.java:77)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:695)

POM dependencies:

<dependency>
    <groupId>org.parceler</groupId>
    <artifactId>parceler</artifactId>
    <version>0.2.5</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.parceler</groupId>
    <artifactId>parceler-api</artifactId>
    <version>0.2.5</version>
</dependency>

This looks like it could be related to: johncarl81/transfuse#69

Does not work because of javax.annotations.Nonnull in dependent JAR

Hi,

I found this project very promising but I'm not able to use it as I'm dependent on other projects using com.google.code.findbugs:jsr305:1.3.9 in their dependencies.

And it conflicts with javax.annotations.Nonnull in transfuse-bootstrap jar and DEX is not able to compile such a project.

Please remove this class form your project and use external dependcy instead.

Thanks

ClassNotFoundException when using Parceler with savedInstanceState

Steps to reproduce:

  • Use Parcels.wrap() in onSaveInstanceState() method of a Fragment (from v4 support lib),
  • Use Parcels.unwrap() in onActivityCreated() of the same Fragment.

Desired effect:
Reference to unmarshalled object returned from unwrap().

Current behavior:
Exception thrown: BadParcelableException: ClassNotFoundException when unmarshalling: [my_class]$$Parcelable

The $$Parcelable classes are created during build; the correct types are mapped in Parceler$$Parcels class. Problem does not appear when using custom Bundle instances (they use a BootClassLoader by default) or passing in an Intent (where the extras bundle uses a PathClassLoader). Checked on Nexus 5 with Android 4.4, Nexus 4 with 4.4.2, (both with ART runtime), Galaxy S3 (4.3.1, dalvik).

No ability to suppress reflection required messages

Warning:(25, 24) Parceler: Reflection is required to modify private field: String secret, consider using non-private.
Warning:(25, 24) Parceler: Reflection is required to access private field: String secret, consider using non-private.

I am already using transient on static fields, but I am using @Parcel on a class that I am also using with GSON for serialisation, so I can't add transient to the private fields as that has a different meaning in GSON (it will not serialise the field).

I am using the private access level by design, so I want to be able to suppress this warning. Could you advise me how to do this?

Annotation processing is stuck in eclipse

I use eclipse to develop and build my projects. From the command line, i can compile with maven, but unfortunately eclipse cannot do that. The annotation processing is started, but somewhere it is stuck. I debugged the processing, and i made it to TransactionProcessorPool.execute(). Here the ExecutorService.execute() method is called, but the execution is stuck at ExecutorService.awaitTermination(). I guess the Transaction goes into a forever loop or something. Unfortunately i could not debug it any deeper.

I am using eclipse 4.3.2 on Windows 8. This is the sample project what i used.

Usage of parceler (@Parcel) with Realm.io (Android)

I have the following code which produces the error: Error:Parceler: Unable to find read/write generator for type io.realm.Realm for io.realm.RealmObject.realm

It was working all fine without extends RealmObject , however I want to use Realm to put to database easily. Is there a way to exlcude the RealmObject fields and just use the basic pojo fields for @parcel?

    @Parcel
    public class Feed extends RealmObject{
        int id;
        public String text;
        public String time_created;
        String time_modified;
        int comments_count;
        int likes_count;
        String feed_type;
        int obj_id;
        String image;
        String user_name;
        String user_earthmile_points;
        boolean liked;
        boolean commented;
        boolean is_private;
        String url;
        int feed_creator_id;
  }

org.parceler.ParcelerRuntimeException: Unable to create ParcelableFactory for com.example.projects.Foo

Hi johncarl81,

I'm using Parceler on my project but I get the error on title. My configuration is:

Parceler library, version 0.2.10
Gradle plugin, version 0.12+

on build.gradle:

def parcelerVersion = '0.2.10'

dependencies{
compile "org.parceler:parceler-api:${parcelerVersion}"
provided "org.parceler:parceler:${parcelerVersion}"
}

the class Foo is made as following:

@Parcel
public class Foo extends FooParent {
...
}

The FooParent class is a class of an external library used on the project.

I've also tried another configuration, like this:

@ParcelClass(FooParent.class)
public class Foo extends FooParent {
...
}

In both cases, I get mentioned error. Can you give me some help? I find this library very useful and certainly I will use it on other my projects.

PS: another one thing, in my case the configuration of build.gradle

dependencies{
compile "org.parceler:parceler-api:${parcelerVersion}"
apt "org.parceler:parceler:${parcelerVersion}"
}

doesn't work.

Interest in static factory

Would anyone like to see Parceler integrate with Google's Autovalue? Unfortunately there are some caveats...

I was curious if Parceler could integrate with AutoValue (https://github.com/google/auto/tree/master/value) to make for super simple Parcelables. What was required was to introduce an alternative way to build a @Parcel bean, namely through a static factory method. By annotating this method with @ParcelFactory, Parceler will pick it up and use it as an alternative to the constructor. Here's what the current working api looks like:

@AutoValue
@Parcel
public abstract class ExampleParcel {

    @ParcelProperty("message")
    public abstract String getMessage();

    @ParcelFactory
    public static ExampleParcel create(@ParcelProperty("message") String message) {
        return new AutoValue_ExampleParcel(message);
    }
}

There are a couple of rough edges here:

First, Parceler's default serialization mode relies on fields. Because the fields in the AutoValue generated bean AutoValue_ExampleParcel are final, writing to them is problematic.

Second, Parceler's method serialization mode follows the java bean get/set syntax. Parceler will only use getter and setters that are properly named (get_, set_) and are public and have the two in pairs. Of course with AutoValue's goal of writing immutable beans, this is not possible, thus we need to use the @ParcelProperty for every static factory input / getter pair (yes, very verbose).

Third, AutoValue produces a class (AutoValue_ExampleParcel) that is package private. Unless this class resides in the org.parceler package, then it cannot be mapped to the Parceler$$Parcels class and thus will not be available via the Parcels.wrap() utility method. The alternative is to reference the generated Parcelable class like so:

intent.putExtra(EXTRA_EXAMPLE_PARCEL, new ExampleParcel$$Parcelable(exampleParcel));

These seem like the only problems that arise with this mapping. I have to say, I like the promise of this, but it ends up being very verbose to map between the two technologies. Would anyone like this functionality to be integrated into Parceler?

The implementation of this is on the staticfactory branch.

Unable to create ParcelableFactory exception

I get the following exception:

05-25 14:24:08.722: E/AndroidRuntime(1335): org.parceler.ParcelerRuntimeException: Unable to create ParcelableFactory for com.example.test.models.Debate

My model:

@Parcel
public class Debate{

    public int id;
    public int category_id;
    public int user_id;

    public String title;
    public String description;
    public String date_human;
    public String code;
    public String username;
    public String comments_count;

    public ArrayList<Comment> comments;
    public ArrayList<String> user_thumbs;

    public void setTitle(String value){
        this.title = value;
    }

    public void setDescription(String value){
        this.description = value;
    }

    public void setUsername(String value){
        this.username = value;
    }

    public void setDateHuman(String value){
        this.date_human = value;
    }

    public void setCommentsCount(String value){
        this.comments_count = value;
    }

    public void setUserThumbs(ArrayList list){
        this.user_thumbs = list;
    }

    public Debate setup(JSONObject item) throws JSONException
    {
        this.setTitle(item.getString("title"));
        this.setDescription(item.getString("description"));
        this.setUsername(item.getString("username"));
        this.setCommentsCount(item.getString("comments_count"));
        this.setDateHuman(item.getString("date_human"));
        this.setUserThumbs(Helper.jsonToArrayList(item.getJSONArray("user_thumbs")));
        return this;
    }

}

Any toughts? Thanks.

Ignore static (and maybe final) variables

I have some static final constants defined in one of my Parcel classes that's causing errors on serialization

error: cannot assign a value to final variable STATUS_OFFLINE

Generic class support

I am trying to use parceler with a generic class I defined, this is a simplified example:

@Parcel
public class ParcelableObject {
    ParcelableInner<Integer> parcelableInner;
}

@Parcel
public class ParcelableInner<T> {
    T i;
}

Running it I get an exception:

Exception in thread "pool-177-thread-2" org.parceler.ParcelerRuntimeException: Unable to find appropriate Parcel method to write java.lang.Object

So I create a Converter to manual define how to convert the inner class:

@Parcel
@ParcelClass(value = ParcelableInner.class, converter = ParcelableInnerConverter.class)
public class ParcelableObject {
    ParcelableInner<Integer> parcelableInner;
}

public class ParcelableInner<T> {
    T i;
}

But I get a different error:

Exception in thread "pool-185-thread-1" org.parceler.ParcelerRuntimeException: Unable to find appropriate Parcel method to write it.cosenonjaviste.ParcelableInner

This error seems to be related to generic definition, so I removed the generic:

@Parcel
@ParcelClass(value = ParcelableInner.class, converter = ParcelableInnerConverter.class)
public class ParcelableObject {
    ParcelableInner parcelableInner;
}

public class ParcelableInner {
    Object i;
}

And the error is the first one again:

Exception in thread "pool-194-thread-1" org.parceler.ParcelerRuntimeException: Unable to find appropriate Parcel method to write java.lang.Object

In my opinion the last example is valid, I am using a converter so the framework validation is not needed. What do you think? Is there a different solution to use generic classes?

Parceler crashes when running

Hi John,

Thanks for all that you do in this project. I really want to use it but I've been having trouble getting it to run on even a blank app.

I'm using Android Studio 0.4.4 and created a brand new project. The only thing I did was go into File -> Project Structure -> Modules -> Dependencies and added Parceler there. I've added 0.2.6 and 0.2.7, with or without the API and no order matters.

Looking through the Verbose logs don't reveal anything interesting other than the program simply stops running.

Any ideas?

build.gradle

apply plugin: 'android'

android {
    compileSdkVersion 19
    buildToolsVersion '19.0.0'

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile 'com.android.support:appcompat-v7:+'
    compile fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
    compile 'org.parceler:parceler:0.2.6@jar'
}

support wrapping and unwrapping of list and array types

Would be nice to overload the wrap() method to support the following:
public static <T> Parcelable[] wrap(T[] input)
public static <T> ArrayList<Parcelable> wrap(List<T> input)
public static <T> SparseArray<Parcelable> wrap(SparseArray<T> input)

This way the API can be used directly on collections of Parcelables e.g.:
bundle.putParceableArrayList(Parcels.wrap(myArrayListOfObjects));

NPE when unwrapping null Parcel field

If I have a Parcel with another child Parcel field that's null, I get NPEs during unwrap.

Ideally this should just set the field to null instead of trying to unmarshall a null object.

java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object org.parceler.ParcelWrapper.getParcel()' on a null object reference

example:

@Parcel
public static class Parent {
  Child child;
}

@Parcel
public static class Child {
  // ...
}

unwrapping a parent with a null child will cause NPE

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.