grandstaish / paperparcel Goto Github PK
View Code? Open in Web Editor NEWAuto-generate Parcelable implementations for Java and Kotlin
Home Page: https://grandstaish.github.io/paperparcel/
License: Apache License 2.0
Auto-generate Parcelable implementations for Java and Kotlin
Home Page: https://grandstaish.github.io/paperparcel/
License: Apache License 2.0
I have an Android Java project with some Kotlin files.
Adding PaperParcel breaks Butterknife. With PaperParcel, after ButterKnife.bind(this); the bound views are null.
I reproduced the issue in a fork here, in the java-exemple module.
In java-exemple, remove
compile 'com.github.grandstaish.paperparcel:paperparcel:1.0.0-beta3'
kapt 'com.github.grandstaish.paperparcel:compiler:1.0.0-beta3'
from the build.gradle to check that Butterknife is working when PaperParcel is not used.
I added -keep class nz.bradcampbell.paperparcel.** { *; } to my proguard-rules, which resolves the issue on my end, but if it can't be resolved internally, recommend adding a note in the README.
Excerpt:
E/AndroidRuntime: FATAL EXCEPTION: main
...
java.lang.ExceptionInInitializerError
at nz.bradcampbell.paperparcel.h.a(Unknown Source)
...
Caused by: java.lang.RuntimeException: java.lang.NoSuchFieldException: No field FROM_ORIGINAL in class Lnz/bradcampbell/paperparcel/a; (declaration of 'nz.bradcampbell.paperparcel.a' appears in /data/app/**package name**/base.apk)
...
This was passing before, and with no changes to the travis configuration it somehow decided to fail. If anyone who knows Travis can help with this, I would greatly appreciate it
To demonstrate interoperability
The runtime overhead of instanceof checks actually seems quite high. Also it removes the ability for performance improvements, e.g. not storing an int for null-safety if we know it's not nullable.
These methods are currently used for all boxed primitives. Those types can all be parcelled in the same way as the primitives are.
See the Parcels class in Parceler for reference
The sample app is too simplistic. A better sample would show a parcelling/unparcelling more complex objects
Users should write a TypeAdapter
for any type that would normally be parcelled using serialization.
Although kotlin's compiler knows that List<Value>
can't contain contain null values but List<Value?>
can, the compiled class file loses this information. For that reason, PaperParcel will always do a null-check on every item within a container (e.g. list, map, array, etc). It would be nice to be able to opt-in to say "none of these items can ever be null" and hence remove the extraneous checking.
This page should show how to apply type adapters. It should help reduce the size of the README.
Hi,
I'm seeing an issue in one of my data class I want to parcel, because it contains a LatLng property.
While LatLng does not implement directly Parcelable
interface, it implements SafeParcelable
which itself implements Parcelable
.
I tried to provide a global type adapter for LatLng but it didn't seem to work:
@GlobalTypeAdapter
class LatLngParcelTypeAdapter : TypeAdapter<LatLng> {
override fun readFromParcel(parcel: Parcel): LatLng {
return parcel.readParcelable(LatLng::class.java.classLoader)
}
override fun writeToParcel(latLng: LatLng, parcel: Parcel) {
parcel.writeParcelable(latLng, 0)
}
}
Even though it would work, it would still be nice that the library recognises the type and uses it as a Parcelable ready entity.
Thanks for great library,
Lukasz
It should be actually really easy to support AutoValue using this.
Having annotation is quite small code change. But would it be possible to have extension which accepts an object and saves/load it from parcel.
At least current API could be improved with extension to avoid using util classes
Attempt to be a good Android citizen and keep the generated classes as light on the method count as possible. This will remove one method per generated class.
This constructor is not needed as the data class can be built directly inside of the CREATOR iteself.
Say we have a simple Kotlin data class:
@PaperParcel
data class File(val filePath: String) {
}
We want to determine the file name using the path. One approach is to add a function:
fun name(): String {
val name: String
// Calculate file name from path
return name
}
This makes us calculate the name often. Instead, we choose to use a delegated property:
val name: String by lazy {
// Calculate file name from path. Done only once
}
This breaks the compiler as the name
is a delegated property, not a member property. Using @GetterMethodName
also doesn't work for this reason.
I'm not sure how this should work yet, but some things to consider are:
T
is List<Date>
, then any scoped TypeAdapter<Date>
must still be used to parcel the dates.T
can only be determined at runtime so it won't be possible to make this fail at compile-time if it is used with some non-parcelable value.For example,
@PaperParcel
public class EmptyObject implements Serializable {
}
@PaperParcel
public class Parent {
private EmptyObject o;
public Parent(EmptyObject o) {
this.o = o;
}
}
The generated Parcel for Parent
will write EmptyObject
using serialization instead of the generated Parcel for EmptyObject
Include how to parcel a kotlin object too, because it currently isn't called out. E.g.:
@PaperParcel
object State : PaperParcelable {
@JvmField val CREATOR = PaperParcelable.Creator(State::class.java)
}
If PaperParcel is used in a library project and a consuming app of that library also uses PaperParcel, then there will be a conflict as PaperParcelMapping
will generate under the same package name. This needs to be resolved before 1.0.0.
The additional 'dataparcel' is redundant
I'm not using auto value in my project, and it looks like the dependency you require for the compiler doesn't exist:
Error:Could not find com.google.auto:auto-common:1.0-SNAPSHOT.
Searched in the following locations:
https://jcenter.bintray.com/com/google/auto/auto-common/1.0-SNAPSHOT/maven-metadata.xml
https://jcenter.bintray.com/com/google/auto/auto-common/1.0-SNAPSHOT/auto-common-1.0-SNAPSHOT.pom
https://jcenter.bintray.com/com/google/auto/auto-common/1.0-SNAPSHOT/auto-common-1.0-SNAPSHOT.jar
https://dl.bintray.com/intercom/intercom-maven/com/google/auto/auto-common/1.0-SNAPSHOT/maven-metadata.xml
https://dl.bintray.com/intercom/intercom-maven/com/google/auto/auto-common/1.0-SNAPSHOT/auto-common-1.0-SNAPSHOT.pom
https://dl.bintray.com/intercom/intercom-maven/com/google/auto/auto-common/1.0-SNAPSHOT/auto-common-1.0-SNAPSHOT.jar
https://clojars.org/repo/com/google/auto/auto-common/1.0-SNAPSHOT/maven-metadata.xml
https://clojars.org/repo/com/google/auto/auto-common/1.0-SNAPSHOT/auto-common-1.0-SNAPSHOT.pom
https://clojars.org/repo/com/google/auto/auto-common/1.0-SNAPSHOT/auto-common-1.0-SNAPSHOT.jar
https://jitpack.io/com/google/auto/auto-common/1.0-SNAPSHOT/maven-metadata.xml
https://jitpack.io/com/google/auto/auto-common/1.0-SNAPSHOT/auto-common-1.0-SNAPSHOT.pom
https://jitpack.io/com/google/auto/auto-common/1.0-SNAPSHOT/auto-common-1.0-SNAPSHOT.jar
(...plus my library, removed for privacy)
Required by:
(my app):app:unspecified > com.github.grandstaish.paperparcel:compiler:0.9.8
It should default to 0, but it could be nice to be able to customise the return-value from describeContents().
e.g.
@PaperParcel(describeContents = PARCELABLE_WRITE_RETURN_VALUE)
Maybe Travis CI?
I should be using name()
to write and Enum.valueOf(Class, String)
to read
provided 'com.google.auto.value:auto-value:1.2'
apt 'com.google.auto.value:auto-value:1.2'
Some are out of date, especially @PaperParcel
Finish javadocs in the compiler too
Depends on #34
I'd like to have a generic way to use the generated wrap
/getContents
methods for a given type. In particular, I'd like a single class that has these two methods (that delegates out to the various generated FooParcel
/BarParcel
classes):
public static <ORIG, PARCELABLE extends Parcelable> PARCELABLE wrap(ORIG object)
public static <ORIG, PARCELABLE extends Parcelable> ORIG unwrap(PARCELABLE object)
I started implementing this but realized I should check with you first to make sure this is an enhancement you'd be amenable to. Thoughts?
Hi,
Here is my feedback trying to understand how to use PaperParcel so far.
In the doc :
val example = Example(42)
val parcelableWrapper = ExampleParcel.wrap(example)
In my project I get ExampleParcel unresolved reference, so I checked the samples but the generated class StateParcel is not used anywhere. If I add StateParcel.wrap(state) in the sample I get the same error. Is there something wrong with the docs / readme ? or did I miss something obvious regarding generated classes? (most likely ; )
Unfortunately this is another API breaking change, but it needs to be done before the 1.0 release
Property handle all java.util.Set
collections
Currently there is 2 adapter instance created on the fly for each variable that uses an adapter (one for reading, one for writing). There should probably just be one instance of each type of adapter, and that can be used from any parcelable wrapper.
Simple app showing off regular usage, and also custom usage with TypeAdapters.
So that people know they can be used
Source: rharter/auto-value-parcel#26
This means you won't be able to import the Kotlin and either java one in the same project. Question is, does this matter?
e.g.:
@PaperParcel(typeAdapters = arrayOf(DateTypeAdapter::class))
data class Root(val child: Child<Date>) : PaperParcelable
data class Child<T>(val something: T)
In this example, dates are still parcelled using Serializable.
Need to ensure that the returned type is the correct type and that the getter method has no parameters. Can also allow for package/public scoped variables to avoid using a getter method at all.
1.0.0-beta3 fails on run with:
Information:Gradle tasks [clean, :app:generateDebugSources, :app:generateDebugAndroidTestSources, :app:prepareDebugUnitTestDependencies, :app:mockableAndroidJar, :app:compileDebugSources, :app:compileDebugAndroidTestSources, :app:compileDebugUnitTestSources]
:app:clean
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:preReleaseBuild UP-TO-DATE
:app:prepareComAndroidSupportAnimatedVectorDrawable2321Library
:app:prepareComAndroidSupportAppcompatV72321Library
:app:prepareComAndroidSupportCardviewV72321Library
:app:prepareComAndroidSupportDesign2321Library
:app:prepareComAndroidSupportRecyclerviewV72321Library
:app:prepareComAndroidSupportSupportV42321Library
:app:prepareComAndroidSupportSupportVectorDrawable2321Library
:app:prepareComGoogleAndroidGmsPlayServicesBase840Library
:app:prepareComGoogleAndroidGmsPlayServicesBasement840Library
:app:prepareComGoogleAndroidGmsPlayServicesGcm840Library
:app:prepareComGoogleAndroidGmsPlayServicesLocation840Library
:app:prepareComGoogleAndroidGmsPlayServicesMaps840Library
:app:prepareComGoogleAndroidGmsPlayServicesMeasurement840Library
:app:prepareComIsseiaokiSimplecropview1016Library
:app:prepareComJakewhartonRxbindingRxbinding040Library
:app:prepareComSquareupSqlbriteSqlbrite062Library
:app:prepareComTrelloRxlifecycle050Library
:app:prepareComTrelloRxlifecycleComponents050Library
:app:prepareDeHdodenhofCircleimageview200Library
:app:prepareIoIntercomAndroidIntercomSdk1116Library
:app:prepareIoIntercomAndroidIntercomSdkBase1116Library
:app:prepareIoIntercomAndroidIntercomSdkGcm1116Library
:app:prepareIoReactivexRxandroid110Library
:app:prepareDebugDependencies
:app:compileDebugAidl
:app:compileDebugRenderscript
:app:generateDebugBuildConfig
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets
:app:generateDebugResValues UP-TO-DATE
:app:processDebugGoogleServices
:app:generateDebugResources
:app:mergeDebugResources
:app:processDebugManifest
:app:processDebugResources
:app:generateDebugSources
:app:preDebugAndroidTestBuild UP-TO-DATE
:app:prepareDebugAndroidTestDependencies
:app:compileDebugAndroidTestAidl
:app:processDebugAndroidTestManifest
:app:compileDebugAndroidTestRenderscript
:app:generateDebugAndroidTestBuildConfig
:app:generateDebugAndroidTestAssets UP-TO-DATE
:app:mergeDebugAndroidTestAssets
:app:generateDebugAndroidTestResValues UP-TO-DATE
:app:generateDebugAndroidTestResources
:app:mergeDebugAndroidTestResources
:app:processDebugAndroidTestResources
:app:generateDebugAndroidTestSources
:app:preDebugUnitTestBuild UP-TO-DATE
:app:prepareDebugUnitTestDependencies
:app:mockableAndroidJar UP-TO-DATE
:app:compileDebugKotlin
:app:compileDebugJavaWithJavac FAILED
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
java.lang.NoClassDefFoundError: android/os/Parcelable
Information:BUILD FAILED
If I drop down to beta2, everything runs normally. Thoughts?
Currently PaperParcel tries to find a valid constructor for re-constructing the data class. It could also look for setter methods, or even a static factory method. This would improve java usage.
Started to use your library and this was the first idea that came to me: is it possible to somehow use kapt to generate code which would be recognized as an extension function in Kotlin?
This way one could do:
val example = Example(42)
val parcelableWrapper = Example.wrapInParcel()
which I feel is very convenient.
PaperParcel does not currently support Kotlin's object
declaration for singletons, i.e. @PaperParcel object MyObject
. The PaperParcel compiler will generate code that cannot compile, as it attempts to use the MyObject
's private constructor rather than MyObject.INSTANCE
.
There are scenarios where it's convenient to be able to mix singleton objects and instances of non-singleton classes, such as in a collection, and parcel them polymorphically. It would be great if PaperParcel could help.
Hi again,
When trying to parcel a java class that contains null fields, paper parcel crashes because of NPE.
@PaperParcel
public class HomeScreen {
HomePresenter.Result result; // result may be null
HomeScreen(HomePresenter.Result result) {
this.result = result;
}
}
Generates the following HomeScreen Parcel class:
public final class HomeScreenParcel implements TypedParcelable<HomeScreen> {
public static final Parcelable.Creator<HomeScreenParcel> CREATOR = new Parcelable.Creator<HomeScreenParcel>() {
@Override public HomeScreenParcel createFromParcel(Parcel in) {
return new HomeScreenParcel(in);
}
@Override public HomeScreenParcel[] newArray(int size) {
return new HomeScreenParcel[size];
}
};
private final HomeScreen data;
private HomeScreenParcel(HomeScreen data) {
this.data = data;
}
private HomeScreenParcel(Parcel in) {
ResultParcel resultParcel = ResultParcel.CREATOR.createFromParcel(in);
HomePresenter.Result result = resultParcel.getContents();
this.data = new HomeScreen(_data_state, result);
}
public static final HomeScreenParcel wrap(HomeScreen data) {
return new HomeScreenParcel(data);
}
public HomeScreen getContents() {
return data;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
HomePresenter.Result result = data.result;
ResultParcel resultParcel = ResultParcel.wrap(result);
resultParcel.writeToParcel(dest, 0);
}
}
And Result Parcel, when the NPE happens
public final class ResultParcel implements TypedParcelable<HomePresenter.Result> {
public static final Parcelable.Creator<ResultParcel> CREATOR = new Parcelable.Creator<ResultParcel>() {
@Override public ResultParcel createFromParcel(Parcel in) {
return new ResultParcel(in);
}
@Override public ResultParcel[] newArray(int size) {
return new ResultParcel[size];
}
};
private final HomePresenter.Result data;
private ResultParcel(HomePresenter.Result data) {
this.data = data;
}
private ResultParcel(Parcel in) {
PlaceParcel placeParcel = PlaceParcel.CREATOR.createFromParcel(in);
Place place = placeParcel.getContents();
this.data = new HomePresenter.Result(place);
}
public static final ResultParcel wrap(HomePresenter.Result data) {
return new ResultParcel(data);
}
public HomePresenter.Result getContents() {
return data;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
Place place = data.getPlace(); // Crashes here because data is null
PlaceParcel placeParcel = PlaceParcel.wrap(place);
placeParcel.writeToParcel(dest, 0);
}
}
Removing these methods would be a savings of 2 methods per generated class. With Android's 65k dex limit, even these small savings are relevant. This is controversial because it's a breaking change.
The field in the wrapper would be public
and final
, so it could be accessed without a getter method.
I feel this is OK, because the library aims (for the most part) for these wrappers to go unnoticed using the new PaperParcelable
API (or using AutoValue).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.