Posted by Clément Béra, Senior software program engineer
Data are a brand new Java characteristic for immutable information provider courses launched in Java 16 and Android 14. To make use of data in Android Studio Flamingo, you want an Android 14 (API degree 34) SDK so the java.lang.Report class is in android.jar. That is accessible from the “Android UpsideDownCake Preview” SDK revision 4. Data are primarily courses with immutable properties and implicit hashCode, equals, and toString strategies based mostly on the underlying information fields. In that respect they’re similar to Kotlin information courses. To declare a Particular person document with the fields String title and int age to be compiled to a Java document, use the next code:
|
The construct.gradle file additionally must be prolonged to make use of the proper SDK and Java supply and goal. At the moment the Android UpsideDownCake Preview is required, however when the Android 14 last SDK is launched use “compileSdk 34” and “targetSdk 34” instead of the preview model.
android { |
Data don’t essentially deliver worth in comparison with information courses in pure Kotlin packages, however they let Kotlin packages work together with Java libraries whose APIs embody data. For Java programmers this permits Java code to make use of data. Use the next code to declare the identical document in Java:
public document Particular person(String title, int age) {} |
Moreover the document flags and attributes, the document Particular person is roughly equal to the next class described utilizing Kotlin supply:
class PersonEquivalent(val title: String, val age: Int) {
|
It’s attainable in a document class to override the hashCode, equals, and toString strategies, successfully changing the JVM runtime generated strategies. On this case, the conduct is user-defined for these strategies.
Report desugaring
Since data should not supported on any Android system immediately, the D8/R8 desugaring engine must desugar data: it transforms the document code into code appropriate with the Android VMs. Report desugaring entails reworking the document right into a roughly equal class, with out producing or compiling sources. The next Kotlin supply exhibits an approximation of the generated code. For the appliance code measurement to stay small, data are desugared in order that helper strategies are shared in between data.
class PersonDesugared(val title: String, val age: Int) { |
Report shrinking
R8 assumes that the default hashCode, equals, and toString strategies generated by javac successfully symbolize the interior state of the document. Subsequently, if a area is minified, the strategies ought to replicate that; toString ought to print the minified title. If a area is eliminated, for instance as a result of it has a relentless worth throughout all situations, then the strategies ought to replicate that; the sector is ignored by the hashCode, equals, and toString strategies. When R8 makes use of the document construction within the strategies generated by javac, for instance when it appears to be like up fields within the document or inspects the printed document construction, it is utilizing reflection. As is the case for any use of reflection, you will need to write hold guidelines to tell the shrinker of the reflective use in order that it will probably protect the construction.
In our instance, assume that age is the fixed 42 throughout the appliance whereas title isn’t fixed throughout the appliance. Then toString returns completely different outcomes relying on the principles you set:
Particular person(“John”, 42).toString();
|
Reflective use instances
Protect toString conduct
Say you will have code that makes use of the precise printing of the document and expects it to be unchanged. For that you will need to hold the total content material of the document fields with a rule resembling:
-keep,allowshrinking class Particular person |
This ensures that if the Particular person document is retained within the output, any toString callproduces the very same string as it could within the unique program. For instance:
Particular person("John", 42).toString(); |
Nevertheless, for those who solely need to protect the printing for the fields which can be really used, you may let the unused fields to be eliminated or shrunk with allowshrinking:
-keep,allowshrinking class Particular person |
With this rule, the compiler drops the age area:
Particular person("John", 42).toString(); |
Protect document members for reflective lookup
If you have to reflectively entry a document member, you usually must entry its accessor methodology. For that you will need to hold the accessor methodology:
-keep,allowshrinking class Particular person |
Now if situations of Particular person are within the residual program you may safely search for the existence of the accessor reflectively:
Particular person("John", 42)::class.java.getDeclaredMethod("title").invoke(obj); |
Discover that the earlier code accesses the document area utilizing the accessor. For direct area entry, you have to hold the sector itself:
-keep,allowshrinking class Particular person |
Construct programs and the Report class
If you happen to’re utilizing one other construct system than AGP, utilizing data could require you to adapt the construct system. The java.lang.Report class just isn’t current till Android 14, launched within the SDK from “Android UpsideDownCake Preview” revision 4. D8/R8 introduces the com.android.instruments.r8.RecordTag, an empty class, to point {that a} document subclass is a document. The RecordTag is used in order that directions referencing java.lang.Report can straight be rewritten by desugaring to reference RecordTag and nonetheless work (instanceof, methodology and area signatures, and so forth.).
Which means that every construct containing a reference to java.lang.Report generates an artificial RecordTag class. In a state of affairs the place an software is cut up in shards, every shard being compiled to a dex file, and the dex recordsdata put collectively with out merging within the Android software, this might result in duplicate RecordTag class.
To keep away from the problem, any D8 intermediate construct generates the RecordTag class as a worldwide artificial, in a unique output than the dex file. The dex merge step is then in a position to accurately merge world synthetics to keep away from sudden runtime conduct. Every construct system utilizing a number of compilation resembling sharding or intermediate outputs is required to help world synthetics to work accurately. AGP absolutely helps data from model 8.1.