Postman


Source link: https://github.com/Workday/postman

postman

Postman is a java library that uses code generation to handle the details of implementing the Parcelable interface on Android.

Latest Version:

Build Status:

The Problem

Postman is intended to be used in cases where you have parcelable classes with a lot of fields that need to be serialized. At Workday, we had a lot of classes like the following to represent the responses from server.

public class MyParcelable implements Parcelable {

int myInt;
  String myString;
  MyChildParcelable myChildParcelable;
  ArrayList<MyChildParcelable> myParcelableList;
  ArrayList<String> myStringList;

public static final Creator<MyParcelable> CREATOR = new Creator<MyParcelable>() {

 @Override

public MyParcelable createFromParcel(Parcel source) {

 MyParcelable myParcelable = new MyParcelable();

 Bundle bundle = source.readBundle();

 myParcelable.myInt = bundle.getInt("myInt");

 myParcelable.myString = bundle.getString("myString");

 myParcelable.myChildParcelable = bundle.getParcelable("myChildData");

 myParcelable.myParcelableList = bundle.getParcelableArrayList("myParcelableList");

 myParcelable.myStringList = bundle.getStringArrayList("myStringList");

 return myParcelable;

}

 @Override

public MyParcelable[] newArray(int size) {

 return new MyParcelable[size];

}

  
}
;

@Override
  public int describeContents() {

return 0;
  
}

@Override
  public void writeToParcel(Parcel dest, int flags) {

Bundle bundle = new Bundle();

bundle.putInt("myInt", myInt);

bundle.putString("myString", myString);

bundle.putParcelable("myChildData", myChildParcelable);

bundle.putParcelableArrayList("myParcelableList", myParcelableList);

bundle.putStringArrayList("myStringList", myStringList);

dest.writeBundle(bundle);

  
}
 
}

If you have to write several classes like this, it gets very tedious and tiresome very quickly. And if you're like most software developers, you want to avoid tedious and tiresome like the plague.

The Solution

There is nothing fancy or unexpected in making a class parcelable. There is a lot of boiler plate and it all follows the same pattern. We could write a program that writes this code for us. So we did.

We wrote an annotation processor that can read through a class that you mark as a candidate for processing, and it will generate all the code in the Creator and in writeToParcel(Parcel, int). The same class from above now becomes this:

@Parceled public class MyParcelable implements Parcelable {

int myInt;
  String myString;
  MyChildParcelable myChildParcelable;
  ArrayList<MyChildParcelable> myParcelableList;
  ArrayList<String> myStringList;

public static final Creator<MyParcelable> CREATOR = Postman.getCreator(MyParcelable.class);

@Override
  public int describeContents() {

return 0;
  
}

  @Override
  public void writeToParcel(Parcel dest, int flags) {

Postman.writeToParcel(this, dest);

  
}
 
}

That's all you need to do get Postman working!

How to Use Postman

Add the following lines to your build.gradle file, replacing $postman_version with latest version from Maven Central.

repositories {

  mavenCentral() 
}
  dependencies {

  compile "com.workday:postman:$postman_version"
  compile "com.workday:postman-processor:$postman_version" 
}

Note that if you use the android-apt plugin or the kotlin-android plugin, you may use apt or kapt respectively instead of compile for postman-processor, e.g.

apt "com.workday:postman-processor:$postman_version"

Postman Idioms

The previous example demonstrates the most common way you will use Postman: annotate the class in question with @Parceled. Postman will pick up all member fields in the class and write them to or read them from the Parcel when Postman.writeToParcel(Object, Parcel) or Postman.readFromParcel(Class, Parcel) is called.

Unfortunately, there is still some boiler plate code you have to deal with. In your parcelable class, you must include the following lines:

public static final Creator<MyParcelable> CREATOR = Postman.getCreator(MyParcelable.class);
  @Override public int describeContents() {

return 0; 
}
  @Override public void writeToParcel(Parcel dest, int flags) {

Postman.writeToParcel(this, dest);
 
}

replacing MyParcelable with your own class name. We hope you agree though that this is much less painful than writing the full implementations yourself.

However, to make this part easier, we have included a live template that you can use in Android Studio. Include AndroidParcelable.xml in the following directory depending on your operating system.

  • Windows: <your home directory>\.AndroidStudio<version number>\config\templates
  • Linux: ~/.AndroidStudio<version number>/config/templates
  • OS X: ~/Library/Preferences/AndroidStudio<version number>/templates

Restart Android Studio. Then in your Parcelable class, type postman on an empty line and hit enter. Android Studio will write the block for you (sans imports).

What if there's a field I don't want to include in the Parcel?

In that case, annotate the offending field with @NotParceled.

What if I don't want to include most of the fields in the Parcel?

No problem. In that case, instead of annotating the class with @Parceled, annotate the fields you want included with @Parceled. All other fields will be ignored.

Things to Watch Out For

  • Postman cannot access private fields. Any field you want to include in the Parcel must be either package-private (aka default) or public. If you annotate a private field with @Parceled, Postman will generate a compilation error. A private field in a class annotated with @Parceled will generate a compiler warning.
  • Postman cannot populate final fields. If you annotate a final field with @Parceled, Postman will generate a compilation error. A final field in a class annotated with @Parceled will generate a compiler warning.
  • Postman requires a public or package-private, no arg constructor in order to instantiate the class. A class marked with @Parceled that does not have default constructor will generate a compilation error.

Types Postman Can Handle

Postman can write to the Parcel any of the following types.

Note that Postman will compile if it encounters a List<Object> or a Map<String, Object>, but if one of the items is not of a type that Postman can handle, it will throw a runtime exception when it tries to write the object to the parcel.

Working with Proguard

If you're using ProGuard, you must add the following line to your ProGuard rules

-keep class * implements com.workday.postman.parceler.Parceler -dontwarn com.workday.postman.codegen.* 

otherwise your app will blow up.

Postman also doesn't work with obfuscation, so you if you have obfuscation turned on, you'll need to keep all of your parceled classes.

Resources

Dynamic iOS-like blur of underlying Views for Android.

This is a simple Rx Event Bus implementation using Kotlin.

Code beautifier for Android - a wrapper around a WebView running HighlightJS.

That image ViewPager you have to code for every Android project - use this instead.

Android UI library that creates 'chip' clouds.

Map tools for Android.

Topics


2D Engines   3D Engines   9-Patch   Action Bars   Activities   ADB   Advertisements   Analytics   Animations   ANR   AOP   API   APK   APT   Architecture   Audio   Autocomplete   Background Processing   Backward Compatibility   Badges   Bar Codes   Benchmarking   Bitmaps   Bluetooth   Blur Effects   Bread Crumbs   BRMS   Browser Extensions   Build Systems   Bundles   Buttons   Caching   Camera   Canvas   Cards   Carousels   Changelog   Checkboxes   Cloud Storages   Color Analysis   Color Pickers   Colors   Comet/Push   Compass Sensors   Conferences   Content Providers   Continuous Integration   Crash Reports   Credit Cards   Credits   CSV   Curl/Flip   Data Binding   Data Generators   Data Structures   Database   Database Browsers   Date &   Debugging   Decompilers   Deep Links   Dependency Injections   Design   Design Patterns   Dex   Dialogs   Distributed Computing   Distribution Platforms   Download Managers   Drawables   Emoji   Emulators   EPUB   Equalizers &   Event Buses   Exception Handling   Face Recognition   Feedback &   File System   File/Directory   Fingerprint   Floating Action   Fonts   Forms   Fragments   FRP   FSM   Functional Programming   Gamepads   Games   Geocaching   Gestures   GIF   Glow Pad   Gradle Plugins   Graphics   Grid Views   Highlighting   HTML   HTTP Mocking   Icons   IDE   IDE Plugins   Image Croppers   Image Loaders   Image Pickers   Image Processing   Image Views   Instrumentation   Intents   Job Schedulers   JSON   Keyboard   Kotlin   Layouts   Library Demos   List View   List Views   Localization   Location   Lock Patterns   Logcat   Logging   Mails   Maps   Markdown   Mathematics   Maven Plugins   MBaaS   Media   Menus   Messaging   MIME   Mobile Web   Native Image   Navigation   NDK   Networking   NFC   NoSQL   Number Pickers   OAuth   Object Mocking   OCR Engines   OpenGL   ORM   Other Pickers   Parallax List   Parcelables   Particle Systems   Password Inputs   PDF   Permissions   Physics Engines   Platforms   Plugin Frameworks   Preferences   Progress Indicators   ProGuard   Properties   Protocol Buffer   Pull To   Purchases   Push/Pull   QR Codes   Quick Return   Radio Buttons   Range Bars   Ratings   Recycler Views   Resources   REST   Ripple Effects   RSS   Screenshots   Scripting   Scroll Views   SDK   Search Inputs   Security   Sensors   Services   Showcase Views   Signatures   Sliding Panels   Snackbars   SOAP   Social Networks   Spannable   Spinners   Splash Screens   SSH   Static Analysis   Status Bars   Styling   SVG   System   Tags   Task Managers   TDD &   Template Engines   Testing   Testing Tools   Text Formatting   Text Views   Text Watchers   Text-to   Toasts   Toolkits For   Tools   Tooltips   Trainings   TV   Twitter   Updaters   USB   User Stories   Utils   Validation   Video   View Adapters   View Pagers   Views   Watch Face   Wearable Data   Wearables   Weather   Web Tools   Web Views   WebRTC   WebSockets   Wheel Widgets   Wi-Fi   Widgets   Windows   Wizards   XML   XMPP   YAML   ZIP Codes