Annotation Processor for generating Parcelable code

Overview

ParcelablePlease

An AnnotationProcessor for generating Android Parcelable boilerplate code. See this blog entry for comparison with other parcel libraries.

Dependency

Latest version: Maven Central

compile 'com.hannesdorfmann.parcelableplease:annotation:x.x.x'
apt 'com.hannesdorfmann.parcelableplease:processor:x.x.x'

In android studio you need to apply Hugo Visser's awesome android-apt gradle plugin to enable annotation processing.

How to use

Simply annotate the classes you want to make Parcelable with @ParcelablePlease and implement the Parcelable as well as the CREATOR (This step can be automated by using the Android Studio plugin, see below).

@ParcelablePlease
public class Model implements Parcelable {

  int id;
  String name;
  OtherModel otherModel;

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

  @Override public void writeToParcel(Parcel dest, int flags) {
    ModelParcelablePlease.writeToParcel(this, dest, flags);
  }

  public static final Creator<Model> CREATOR = new Creator<Model>() {
    public Model createFromParcel(Parcel source) {
      Model target = new Model();
      ModelParcelablePlease.readFromParcel(target, source);
      return target;
    }

    public Model[] newArray(int size) {
      return new Model[size];
    }
  };
}

The ParcelablePlease annotation processor will generate a class named ClassName + ParcelablePlease for you with all the code for writing and reading data in the Parcel. So from the example above: ModelParcelablePlease is generated and provides two static methods: ModelParcelablePlease.readFromParcel(Model, Parcel) and ModelParcelablePlease.writeToParcel(Model, Parcel, int)

Once you have done this basic setup by connecting the generated code with your Model class you can change the model class, add fields, remove fields etc. without worring about Parcelable because ParcelablePlease will generate the code for you everytime you compile.

Android Studio Plugin

Like mentioned above you have to write few lines of code to connect the Parcelable class with the generated code. Don't worry, you don't have to do this by hand. There is a Android Studio / IntelliJ plugin that can do that for you:

  1. Open Android Studio / IntelliJ
  2. Open the Preferences (on Mac with ⌘ + ; )
  3. Type in the searchbox "plugin" to navigate quickly to the plugins section
  4. Click on Browse repositories... button
  5. Search for ParcelablePlease and install this plugin
  6. Restart Android Studio
  7. Create a Model class and open the Generate Menu (on Mac with ``⌘ + n` ). Note that the cursor must be somewhere in the code of the class.

Preferences

Remember that you may have to compile your project to make Android Studio run annotation Processing which will generate the ParcelPlease classes.

Supported types

  • Primitives

    • byte
    • boolean
    • double
    • float
    • int
    • long
    • String
  • Primitive wrappers

    • Byte
    • Boolean
    • Double
    • Float
    • Int
    • Long
  • Android specific

    • Parcelable (anything that implements Parcelable)
    • Bundle
    • SparseBooleanArray
  • Arrays

    • int[]
    • long[]
    • double[]
    • String[]
    • float[]
    • char[]
    • boolean[]
    • byte[]
    • Parcelable[] - array of anything that implements Parcelable
  • Other

    • Serializable
    • java.util.Date (by simpling passing time as millis)
  • Collections

    • List<? extends Parcelalble>
    • ArrayList<? extends Parcelable>
    • LinkedList<? extends Parcelable>
    • CopyOnWriteArrayList<? extends Parcelable>
    • List

Bagger

Do you want to make a field Parcelable but it's not listed in the supported types list from above (i.e. java.util.Map)? No Problem: You can provide your own implementation implementing a ParcelBagger like this:

public class DateBagger implements ParcelBagger<Date> {

  @Override public void write(Date value, Parcel out, int flags) {
    if (value == null) {
      out.writeLong(-1);
    } else {
      out.writeLong(value.getTime());
    }
  }

  @Override public Date read(Parcel in) {

    long timeMillis = in.readLong();
    if (timeMillis == -1) {
      return null;
    }

    return new Date(timeMillis);
  }
}

You can use your ParcelBagger with the @Bagger annotation like this:

@ParcelablePlease
public class Person implements Parcelable {

  int id;
  String name;
  
  @Bagger(DateBagger.class)
  Date date;
  
}

Remember that you have to take care about special cases like what if the value is null. Note that java.util.Date is already supported by ParcelablePlease. The example above is just to give you an idea of how a implementation could look like.

Configuration

You can configure which fields should be serialized. There are two ways:

  1. As default all class (and super classes) fields will be serialized. You can mark field's you don't want to serialize by annotating them with @ParcelableNoThanks
  2. You can do the other way: You could change the settings to only serialize fields that are marked with @ParcelableThisPlease like this:
@ParcelablePlease( allFields = false)
public class Animal implements Parcelable {
   
   @ParcelableThisPlease
   String name;
   
   int age; // This will not be serialized 
   
}

As default ParcelablePlease will throw a compile error if it tries to serialize private fields (private fields are not supported because of visibility issues). If your class marked with @ParcelablePlease contains private fields you could mark them as not parcelable with @ParcelableNoThanks or you could cofigure ParcelablePlease to skip private fields by using @ParcelablePlease( ignorePrivateFields = true):

@ParcelablePlease( ignorePrivateFields = true)
public class Person implements Parcelable {
   
   String name;
   
   private int age; // No compile error 
   
}

Limitations

  • Fields must have at least default (package) visibility. That means private fields are not supported.
  • Private classes are not supported because of visibilitiy issues
Comments
  • Provide Android Studio plugin via Plugin-Repository

    Provide Android Studio plugin via Plugin-Repository

    This would tremendously ease the update-process of your awesome plugin as we developers get a update-notification and its simply a two-click process to update your plugin this way.

    Here is the official documentation for that:

    https://www.jetbrains.com/idea/help/preparing-plugins-for-publishing.html

    opened by ajans 6
  • Feature: optional hashCode, equals, toString generation

    Feature: optional hashCode, equals, toString generation

    Hi, as in topic, it would be great if you could include that. Do you even thing it's suitable request? Personally I think that would be useful in most scenarios.

    enhancement 
    opened by MikolajKakol 3
  • ParcelablePlease Intelij plugin error

    ParcelablePlease Intelij plugin error

    cannot create class "com.hannesdorfmann.parcelableplease.plugin.ParcelablePleaseAction" [Plugin: com.hannesdorfmann.parcelableplease.plugin]: cannot create class "com.hannesdorfmann.parcelableplease.plugin.ParcelablePleaseAction" [Plugin: com.hannesdorfmann.parcelableplease.plugin]
    com.intellij.diagnostic.PluginException: cannot create class "com.hannesdorfmann.parcelableplease.plugin.ParcelablePleaseAction" [Plugin: com.hannesdorfmann.parcelableplease.plugin]
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.convert(ActionManagerImpl.java:287)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.getActionImpl(ActionManagerImpl.java:239)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.getAction(ActionManagerImpl.java:232)
        at com.intellij.openapi.actionSystem.DefaultActionGroup.unStub(DefaultActionGroup.java:345)
        at com.intellij.openapi.actionSystem.DefaultActionGroup.getChildren(DefaultActionGroup.java:303)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl$5.compute(ActionManagerImpl.java:1261)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl$5.compute(ActionManagerImpl.java:1254)
        at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:932)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.preloadActionGroup(ActionManagerImpl.java:1254)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.preloadActionGroup(ActionManagerImpl.java:1248)
        at com.intellij.codeInsight.generation.actions.GenerateAction.preload(GenerateAction.java:91)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.preloadActionGroup(ActionManagerImpl.java:1266)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.preloadActionGroup(ActionManagerImpl.java:1269)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.preloadActionGroup(ActionManagerImpl.java:1248)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.doPreloadActions(ActionManagerImpl.java:1236)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.access$200(ActionManagerImpl.java:73)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl$4.run(ActionManagerImpl.java:1220)
        at com.intellij.openapi.application.impl.ApplicationImpl$8.run(ApplicationImpl.java:419)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        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:745)
        at com.intellij.openapi.application.impl.ApplicationImpl$1$1.run(ApplicationImpl.java:149)
    Caused by: com.intellij.diagnostic.PluginException: com/hannesdorfmann/parcelableplease/plugin/ParcelablePleaseAction : Unsupported major.minor version 52.0 [Plugin: com.hannesdorfmann.parcelableplease.plugin]
        at com.intellij.ide.plugins.cl.PluginClassLoader.loadClassInsideSelf(PluginClassLoader.java:130)
        at com.intellij.ide.plugins.cl.PluginClassLoader.tryLoadingClass(PluginClassLoader.java:77)
        at com.intellij.ide.plugins.cl.PluginClassLoader.loadClass(PluginClassLoader.java:66)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:270)
        at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.convert(ActionManagerImpl.java:262)
        ... 23 more
    Caused by: java.lang.UnsupportedClassVersionError: com/hannesdorfmann/parcelableplease/plugin/ParcelablePleaseAction : Unsupported major.minor version 52.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:643)
        at com.intellij.util.lang.UrlClassLoader._defineClass(UrlClassLoader.java:195)
        at com.intellij.util.lang.UrlClassLoader.defineClass(UrlClassLoader.java:191)
        at com.intellij.util.lang.UrlClassLoader._findClass(UrlClassLoader.java:167)
        at com.intellij.ide.plugins.cl.PluginClassLoader.loadClassInsideSelf(PluginClassLoader.java:124)
        ... 29 more
    
    12:46:14 PluginException: cannot create class "com.hannesdorfmann.parcelableplease.plugin.ParcelablePleaseAction" [Plugin: com.hannesdorfmann.parcelableplease.plugin]: cannot create class "com.hannesdorfmann.parcelableplease.plugin.ParcelablePleaseAction" [Plugin: com.hannesdorfmann.parcelableplease.plugin]
    12:46:46 Throwable: Null child action in group Generate () of class class com.intellij.openapi.actionSystem.DefaultActionGroup, id=generateParcelablePlease
    

    OS: Linux Mint 16 AS: 0.9.3

    Exception occures everytime when I press alt + insert to generate something. ParcelablePlease doesn't even occurs on list.

    opened by aradomski 2
  • Add support for getters and setters

    Add support for getters and setters

    Currently it's impossible to access protected sub-classed fields. For instance: My model inherits from SugarORMs SugarRecord

    package not.in.my.pkg;
    public class SugarRecord<T> {
        protected long id;
        ...
    }
    
    package in.my.package;
    public class MyModel extends SugarRecord<MyModel> {
    } 
    
    package in.my.package;
    public class MyModelParcelablePlease {
        public static void writeToParcel(Venue source, Parcel parcel, int flags) {
            parcel.writeByte( (byte) (source.id != null ? 1 : 0) ); // error: id has protected access in SugarRecord
        }
    }
    

    error: id has protected access in SugarRecord

    If we could use getters and setters, this issue would be solved!

    enhancement 
    opened by Inlustra 0
  • Support for nullables

    Support for nullables

    If it's a Bool (vs. bool), then first a extra byte of != null should be emitted, and then if it's not null, emit the byte representing the value. Same goes for a String - emit a byte, and if not null emit the string. And for any other type...

    Thanks :-)

    opened by danielgindi 1
  • Error in generated code on Parcelable with generics

    Error in generated code on Parcelable with generics

    Using ParcelablePlease on a class with a Parcelable field with a generic parameter there is an error in generated code. For example using ObservableParcelable class of data binding framework:

    ObservableParcelable<App> app = new ObservableParcelable<>();
    

    the generated code has a compilation error:

    target.app = parcel.readParcelable(android.databinding.ObservableParcelable<App>.class.getClassLoader());
    

    It can be fixed easily using a custom bagger:

    public class ObservableParcelableBagger implements ParcelBagger<ObservableParcelable> {
        @Override public void write(ObservableParcelable value, Parcel out, int flags) {
            out.writeParcelable(value, flags);
        }
    
        @Override public ObservableParcelable read(Parcel in) {
            return in.readParcelable(ObservableParcelable.class.getClassLoader());
        }
    }
    

    Thanks for this great framework!

    bug 
    opened by fabioCollini 3
  • CodeGenerator - suggestions

    CodeGenerator - suggestions

    I would have following suggestions:

    1. if I use an abstract base class, the generator should at check the base class fields for private fields as well
    2. the generator could create an empty constructor
    3. it could also create the import statement for @ParcelablePlease annotation
    opened by MFlisar 3
  • Nullpointer

    Nullpointer

    ArrayList<MailsCount> mailsCounts; where MailsCount implements Parcelable.

    Caused by: java.lang.NullPointerException at com.hannesdorfmann.parcelableplease.processor.ParcelablePleaseProcessor.process(ParcelablePleaseProcessor.java:62) at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:793) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:722) 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)

    bug 
    opened by sockeqwe 0
  • Suggestion for API change to remove more boilerplate

    Suggestion for API change to remove more boilerplate

    I like that you don't have a subclass like in Parceler and other similar libraries.

    How about changing the code you have to write to something like code below?

    @ParcelablePlease
    public class Model implements Parcelable {
    
      int id;
      String name;
      OtherModel otherModel;
    
      @Override public int describeContents() {
        return 0;
      }
    
      @Override public void writeToParcel(Parcel dest, int flags) {
        ModelParcelablePlease.writeToParcel(this, dest, flags);
      }
    
      public static final Creator<Model> CREATOR = ModelParcelablePlease.creator();
    }
    
    enhancement 
    opened by mg6maciej 1
Releases(1.0.2)
Pure Java code generation tool for generating a fully functional ContentProvider for Android.

RoboCoP RoboCoP is a Java library that can generate a fully-functional ContentProvider from a simple JSON schema file. Get the latest version from our

Rain 246 Dec 29, 2022
A Java API for generating .java source files.

JavaPoet JavaPoet is a Java API for generating .java source files. Source file generation can be useful when doing things such as annotation processin

Square 10k Jan 2, 2023
Annotation Processing Library. Generates proxy class on top of interface/abstract class, that allows to intercept calls. Also known as a design pattern: proxy, delegate, interceptor.

1. AutoProxy Annotation Processing Library. Generates proxy class on top of interface/abstract class, that allows to intercept calls. Also known as a

Oleksandr 19 Nov 24, 2022
:package: Android Parcelables made easy through code generation.

Parceler Have a question? Ask it on StackOverflow. Found an issue? Please report it. In Android, Parcelables are a great way to serialize Java Objects

John Ericksen 3.6k Dec 27, 2022
A custom view styling library for Android that generates the obtainStyledAttributes() and TypedArray boilerplate code for you.

DEPRECATED This project is no longer maintained. Consider using https://github.com/airbnb/paris Barber Barber is your personal custom view stylist. Si

Zac Sweers 716 Dec 30, 2022
A code generator to create Android ContentProvider

DatabaseCodeGenerator This project is a code generator written in Java used to generate Android code. Given a database schema JSON definition file, it

Foxykeep 297 Nov 25, 2022
A Java Code Generator for Pojo Builders

PojoBuilder - A Code Generator for Pojo Builders Author: Michael Karneim Project Homepage: http://github.com/mkarneim/pojobuilder About The PojoBuilde

Michael Karneim 330 Dec 11, 2022
Codegeneration tool for isomorphic server and mobile Go apps with gRPC & Protobuf. Share code between your backend, Android & iOS app! :sun_with_face:

Anakin Codegeneration tool for isomorphic server and mobile Go apps with gRPC & Protobuf. Share code between your backend, Android & iOS app! Descript

Kirill Biakov 17 Jun 25, 2020
A small tool to help you generate android projects that have a base code.

Volt Project A small tool to help you generate android projects that have a base code. Usage Change project in base directory. python volt-gen.py <pac

Victor Varenik 3 Feb 2, 2022
Kotlin code generation for commercetools platform type-safe product-types, reference expansion and custom fields

Kotlin code generation for commercetools platform type-safe product-types, reference expansion and custom fields

null 8 Dec 15, 2022
Janishar Ali 2.1k Jan 1, 2023
Annotation processor that generates a kotlin wrapper class for a java file, enabling named parameters for kotlin callers.

Annotation processor that generates a kotlin wrapper class for a java file, enabling named parameters for kotlin callers.

Josh Skeen 10 Oct 12, 2022
🔦 Showkase is an annotation-processor based Android library that helps you organize, discover, search and visualize Jetpack Compose UI elements

Showkase is an annotation-processor based Android library that helps you organize, discover, search and visualize Jetpack Compose UI elements. With minimal configuration it generates a UI browser that helps you easily find your components, colors & typography. It also renders your components in common situations like dark mode, right-to-left layouts, and scaled fonts which help in finding issues early.

Airbnb 1.7k Jan 2, 2023
KSP annotation processor for Toothpick

toothpick-ksp KSP annotation processor for Toothpick. All credits go to olivierperez/ksp for the initial work on a KSP processor. Bear in mind this is

null 0 Oct 19, 2021
Annotation processor that provides better navigation on android multi-modules projects 🛳.

FlowNav FlowNav is a mobile library for Android that helps and provider a better way to make multi-modules navigation. The main purpose of this librar

Jeziel Lago 134 Nov 16, 2022
Android Annotation Processor library to generate adapter class easily from your model with a lot of customization

Android Annotation Processing Library to generate your adapters only with Annotations on your model, support working with Kapt and KSP Processors

Amr Hesham 63 Nov 24, 2022
An annotation processor library that automatically creates Hilt's `@Binds` functions and modules.

HiltBinder An annotation processor library that automatically creates Hilt's @Binds functions and modules. If you think this library is useful, please

SangMin Park 5 Sep 19, 2022
IntelliJ Plugin for Android Parcelable boilerplate code generation.

IntelliJ/Android Studio Plugin for Android Parcelable boilerplate code generation This tool generates an Android Parcelable implementation based on fi

Michał Charmas 2.1k Dec 27, 2022
Android Parcelable models made easy

AutoParcel AutoParcel is an AutoValue extension that enables Parcelable values generation. Just add implements Parcelable to your @AutoValue annotated

Francesco Sardo 1.4k Dec 23, 2022
Auto-generate the fastest possible Parcelable implementations for Java and Kotlin

This project is deprecated It will still be maintained, but no new features will be added. Please use Parcelize, as it is the official way of generati

Bradley Campbell 492 Nov 17, 2022