epoxy
epoxy copied to clipboard
ViewBinding and proguard rules for obfuscation
If you are using the abstract class ViewBindingEpoxyModelWtihHolder and you have obfuscation with R8 enabled, then the code does not work because it is trying to get the reflected bind method from the ViewBinding class. Since bind is not part of the ViewBinding interface and gets added only in implementations the reflection is the only way to go.
To solve this the following rule should be added to proguard:
-keepclassmembers class <package name of your app>.databinding.** {
public <methods>;
}
ViewBindingEpoxyModelWtihHolder failing once upgrading to compile sdk 31 and arctic fox gradle 7+. Funny thing is, it's crashing in the wrong xml! Not the one which is being used in that screen.
@ubarua123 what is the crash that you are getting, any chance of pasting the crash log?
java.lang.NullPointerException: Missing required view with ID: com.muuzzer_wq.android.apps.readers_writers.community:id/header_title
at com.wonderquill.databinding.HoirzontalRowHeaderBinding.bind(HoirzontalRowHeaderBinding.java:5)
The controller where it crashed, wasn't even inflating this model. I have a build running in production with the same code.
It's only after I upgraded to:
JDK: 11 Gradle: 7.0.4 Arctic Fox
that all my problems started. Worst part is, it's working fine in debug. Obviously it has something to do with proguard. These are my proguard rules if that helps:
-keepclassmembers class * extends androidx.viewbinding.ViewBinding {
public static *** bind(android.view.View);
}
-keepclassmembers class com.wonderquill.databinding.** {
public <methods>;
}
-keep class * implements androidx.viewbinding.ViewBinding {
public static *** bind(android.view.View);
public static *** inflate(android.view.LayoutInflater);
}
This is the model class:
@EpoxyModelClass(layout = R.layout.hoirzontal_row_header)
abstract class HorizontalHeaderModel : ViewBindingEpoxyModelWithHolder<HoirzontalRowHeaderBinding>() {
override fun HoirzontalRowHeaderBinding.bind() {
}
}
same scenario + 1
Both problems can be solved with this proguard rules
-keep class * extends $package.ViewBinding { *;}
-keepclassmembers class * extends $package.ViewBinding { *;}
-keep class * extends $package.path.to.ViewBindingEpoxyModelWithHolder { *;}
-keepclassmembers class * extends $package.path.to.ViewBindingEpoxyModelWithHolder { *;}
and don't forget to change the class paths to point to your package for the ViewBinding classes and to ViewBindingEpoxyModelWithHolder class. Apparently R8 somehow messes up the classes and when the bind method of the ViewBinding class is trying to be resolved, this line
val genericSuperclass = klass.genericSuperclass
will incorrectly resolve the superclass. I've created a vanilla project and tried it with only my classes and the problem is there as well so it has nothing to do with Epoxy per se.
So the solution, even though I don't know the original cause, is to keep those EpoxyModels extending from ViewBindingEpoxyModelWithHolder and don't allow R8 to mess with them
Have anyone experienced a new issue with R8 full mode with ViewBindingEpoxyModelWithHolder -
Fatal Exception: java.lang.NullPointerException: null cannot be cast to non-null type java.lang.Class<*>
at x.ViewBindingEpoxyModelWithHolderKt.getSuperclassParameterizedType(ViewBindingEpoxyModelWithHolder.kt:42)
Have anyone experienced a new issue with R8 full mode with
ViewBindingEpoxyModelWithHolder-Fatal Exception: java.lang.NullPointerException: null cannot be cast to non-null type java.lang.Class<*> at x.ViewBindingEpoxyModelWithHolderKt.getSuperclassParameterizedType(ViewBindingEpoxyModelWithHolder.kt:42)
Same here, a simple but rude fix was adding -keep class com.airbnb.epoxy.kotlinsample.helpers.** { *; } into proguard-rules.pro