Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resource IDs will be non final in AGP 7.0

I have an annotation processing library that generates RecyclerView adapters in compile time.

I'm currently rebuilding it from the ground up with many changes and improvements, but while testing, I received a warning stating:

Resource IDs will be non-final in Android Gradle Plugin version 7.0, avoid using them as annotation attributes

This is a problem because it means I won't be able to use R.layout variables in annotations.

I currently use it to associate the layout file's integer value with the R class variable name; this is to locate the layout file from the resource folder and later call inflate(layoutResId).

Currently, I solve this issue like so

Example

Given a simple ViewHolder annotation.

annotation class ViewHolder(val layoutResId: Int)

With the usage

@ViewHolder(R.layout.sample)
data class Sample(val text: String) : GencyclerModel

And the Generated R.layout class.

public final class R {
    public static final class layout {
        public static final int sample = 567541283;
    }
}

When processing the ViewHolder annotation, the processor would receive the integer value 567541283.

In the first processing cycle, the processor would analyze the R class and create a table to map the integer to the layout name, in this case, 567541283 <-> sample.

With that info, I can iterate over the layout resource directory and find the layout file with the name sample.xml. and I can also later call inflate(R.layout.sample)

The field will be non-final in the new version, thus throw a compile-time error.

An annotation argument must be a compile-time constant.

Possible solutions

  1. (Butterknife solution) Creating a duplicate R class that will generate the R.layout variables as static final, thus removing my R class dependency.

  2. (AndroidAnnotations solution). Using strings instead of the Resources class. I'm not too fond of this solution because it will cause issues if the layout is renamed or a typo.

I'm not sure how happy I feel about both, but I honestly don't see other ways to solve it.

If anyone has a better way to solve this, I would love to hear, and if not, which solution would you prefer?

Thanks

I'm linking the issue that I opened in the GitHub project in case you want to contribute.

like image 436
Gil Goldzweig Avatar asked Nov 07 '22 02:11

Gil Goldzweig


1 Answers

Another solution would be adding a method to GencyclerModel which returns the layout reference and remove that reference from your annotation. I guess the only problem this approach is going to make, is your checking condition about the existence of layout file in your compiler. But using this approach you won't hardcode layout references in annotations and you'll get them from a method inside each model

like image 136
Amin Avatar answered Nov 15 '22 08:11

Amin