grandstaish/paperparcel

What the heck is describe contents doing???

bjesuiter opened this issue ยท 16 comments

Hello dear lib developer,

thanks for this awesome PaperParcel library. I read your Blogpost with the history of this lib in kotlin and why it's interesting to also have it for java based android apps.
However, i have the following problem:

I use AutoValue and did simply include your library and added implements Parcelable.
But now i'm forced to implement a "describeContents" field of type int in my builder / in my constructors of
my AutoValue abstract class.

What is this field supposed to do? And, is it really so important, that I have to add a setter for it? This feels a little bit too intrusive.

Which version of AutoValue are you using? And which version of PaperParcel too?

Im using the following imports for both:

    annotationProcessor "com.google.auto.value:auto-value:1.2"
    provided "com.google.auto.value:auto-value:1.2"

//    compile 'nz.bradcampbell:paperparcel:2.0.0-beta2'
//    annotationProcessor 'nz.bradcampbell:paperparcel-compiler:2.0.0-beta2'

i know, version 2 of your lib is in beta, but it's the default version being advertised on your website and ther's no warning, that someone should use an older version for stability, so I assumed that this beta version is already safe to use in production ;)

The beta is safe and definitely preferred over v1.

Can you try upgrading the AutoValue dependencies to 1.3 and removing any of the code you added for describeContents? That library had a breaking change for AutoValueExtensions in between 1.2 and 1.3, it might be the cause of this.

No, sadly still the same thing. This is my Class:

@AutoValue
public abstract class GotsLocationResult implements Parcelable {
    public abstract ImmutableList<GotsLocation> locations();
    
    public static GotsLocationResult create(List<GotsLocation> locations) {
        return new AutoValue_GotsLocationResult(0, ImmutableList.copyOf(locations));
    }
    
}

As you see, it has only 1 AutoValue field, but requires 2 params for the constructor, the first being the describeContents int.

Additionally i do now have the problem, that another generated AutoValue class with a builder is now complaining, that i can't instantiate the generated Builder, because it's abstract. I saw something about this in the changelog, but I have no idea currently how i have to write builder style AutoValue classes with version 1.3

Even after you do a clean and rebuild? You shouldn't need to do anything with describeContents ๐Ÿค”

Is your project open source? I don't mind opening it up and taking a look

So, i dug a little bit into the generated classes and i found a getter for describeContents.
I already did generate debug sources, maybe it'll help to do full rebuild.

Yes, PaperParcel will generate the following method in the implementation class:

public int describeContents() {
  return 0;
}

This is required for the Parcelable interface. It shouldn't show up in the constructor, and you definitely shouldn't need a setter. Very strange. It's possible it won't work until the builder issue is fixed.

If it doesn't work, perhaps you could send me what's being generated too. I.e. what does the generated code in AutoValue_GotsLocationResult look like?

UPDATE 1

Invalidating IntelliJ Caches did not help :/

Original Post

Same errors after cleanBuild and compileDebugSources:

Builder Problem (probably due to changes in AutoValue 1.3)

 /**
     * For creating a GotsLocation object from a Builder interface
     *
     * @return Builder
     */
    public static Builder builder() {
        return new AutoValue_GotsLocation.Builder()
                .setValid(1)
                .setIntIsHistory(0);
    }

This complains: AutoValue_GotsLocation.Builder() cannot be instantiated because it's abstract. But to my knowledge, this is or was the official way to do AutoValue with builders. Right?

Describe contents problem

@AutoValue
public abstract class GotsLocationResult implements Parcelable {
    public abstract ImmutableList<GotsLocation> locations();
    
    public static GotsLocationResult create(List<GotsLocation> locations) {
        return new AutoValue_GotsLocationResult(ImmutableList.copyOf(locations));
    }
    
}

This complains: AutoValue_GotsLocationResult(int, ImmutableList) cannot be applied to my parameters i give it (obviously I give it only the immutable list without the int)

Now i'm trying to clean the intellij cache and do an intellij restart, maybe the problematic source files where cached before. :/

Ah, and maybe this is helpfull to solve the thing with the builder:
The official changelog from 1.2 to 1.3 states:

Bugs fixed since 1.2

Allow an @AutoValue.Builder to extend a parent builder using the <B extends Builder> idiom.

I think this is the reason, the implementation is somehow missing, but I don't know, how to fix it.

I just created a new project with AutoValue 1.3, and PaperParcel 2.0.0-beta2, and compiled the following class fine:

@AutoValue
public abstract class GotsLocationResult implements Parcelable {
  public abstract int locations();

  static Builder builder() {
    return new AutoValue_GotsLocationResult.Builder();
  }

  @AutoValue.Builder
  public static abstract class Builder {
    abstract Builder locations(int locations);
    abstract GotsLocationResult build();
  }
}

ookayyy ๐Ÿ˜ฎ I have to dig a little bit more into that then

Thanks for your awesomely fast help! ๐Ÿ˜„
I'll add a comment / close the issue on more information :)

Okay, I have found the following things:

RyanHarter (Implementor of auto-value-parcel) said that he discovered, that ItelliJ does sometimes not run it's auto-value extension.

I now get at least differnet error messages. I have a private field on one of my classes, which should be ignored by auto-value, since it's generated from another field on access. But PaperParceller now complains that it cannot write the field since it's private.

Can i somehow exclude the field from being processed by paperParcel?

You can make that field transient. There are also other exclude options available using the @ProcessorConfig API too.

Ah, yes! Thanks for that hint with transient! I thought about that, but i assumed wrongly that transient was an annotation instead of a language keyword.

The problem with the builder was due to incomplete debug sources compiling.
I couldn't compile the sources completely because of this contentDescription error. And this was likely due to intelliJ having some hickups and not invoking the auto-value-extensions for some reason.

After some intellij restarts through the processes of changing dependencies, all things worked as expected ๐Ÿ‘ The contentDescription error was gone, and after adding transient to this one property it compiled correctly with a completely implementet builder ๐Ÿ˜„

Thanks again for your great support! โค๏ธ

Awesome, no worries. Thanks for following up with a detailed description of what the issue was too!