Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LeakCanary crashing app on start: java.lang.AbstractMethodError: androidx.lifecycle.ViewModel #2314

Closed
petrstetka opened this issue Feb 24, 2022 · 15 comments

Comments

@petrstetka
Copy link

petrstetka commented Feb 24, 2022

Description

Hello in our app we use LeakCanary library. We have recently upgraded gradle, kotlin gradle scripts to KTS, etc. Now when we build APK through Android Studio by "Generate Signed APK" or "Generate APKs" or in terminal by "gradlew assembleSomethingDebug" as Debug type it causing crash on start app.
Once I remove the LeakCanary library from debugImplementation in build.gradle.kts. It will stop crashing.

Log:

  java.lang.AbstractMethodError: abstract method "androidx.lifecycle.ViewModel androidx.lifecycle.ViewModelProvider$Factory.create(java.lang.Class, androidx.lifecycle.viewmodel.CreationExtras)"
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:168)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:137)
        at leakcanary.internal.ViewModelClearedWatcher$Companion.install(ViewModelClearedWatcher.kt:52)
        at leakcanary.internal.AndroidXFragmentDestroyWatcher.invoke(AndroidXFragmentDestroyWatcher.kt:66)
        at leakcanary.internal.AndroidXFragmentDestroyWatcher.invoke(AndroidXFragmentDestroyWatcher.kt:25)
        at leakcanary.FragmentAndViewModelWatcher$lifecycleCallbacks$1.onActivityCreated(FragmentAndViewModelWatcher.kt:59)
        at android.app.Application.dispatchActivityCreated(Application.java:353)
        at android.app.Activity.dispatchActivityCreated(Activity.java:1334)
        at android.app.Activity.onCreate(Activity.java:1607)
        at androidx.core.app.ComponentActivity.onCreate(ComponentActivity.java:85)
        at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:343)
        at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:246)
        at com.ilab.spaceti.ui.base.BaseActivity.onCreate(BaseActivity.kt:99)

Version Information

  • LeakCanary version: 2.8.1
  • Android OS version: 12
  • Gradle version: 7.4
  • Android Gradle Plugin: 7.1.1
@petrstetka petrstetka changed the title LeakCanary causing crash app on start LeakCanary causing crash app on start: java.lang.AbstractMethodError: androidx.lifecycle.ViewModel Feb 24, 2022
@petrstetka petrstetka changed the title LeakCanary causing crash app on start: java.lang.AbstractMethodError: androidx.lifecycle.ViewModel LeakCanary crashing app on start: java.lang.AbstractMethodError: androidx.lifecycle.ViewModel Feb 24, 2022
@vxplore
Copy link

vxplore commented Apr 1, 2022

Same thing is happening for me also.
But I could not understand the actual reason, but now i understand the reason and trying to find the solution. Removing the dependency is just a workaround.

@dougnazar
Copy link

Basically lifecycle-2.5.0-alpha01 added a new preferred create() method to ViewModelProvider.Factory that takes an additional CreationExtras parameter. LeakCanary's ViewModelClearedWatcher

doesn't implement this yet, and due to some optimization quirk (I think) it doesn't work if you build a debug APK, but at least for me was working if I deployed an debug version from Studio. I believe it'll would work if compiled against the newer lifecycle version since it defaults to the old version.

public fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
            create(modelClass)

Haven't had any time to test either fix, so I might be way off in left field.

@pyricau
Copy link
Member

pyricau commented Apr 3, 2022

Interesting. Any suggested fix from the LeakCanary side? I worry that updating the dependency version might trigger the same crash for users of older versions of the lib.

Also, can you provide a sample project for repro?

@dougnazar
Copy link

So I first verified that adding that method to ViewModelClearedWatcher does solve this issue for me and I'll be using that as a temporary measure.

I then spent way too much time trying to create a simple repro before realizing the trigger is the minsdk. Anything under API 24 will cause the crash. So it somehow ties into the Java 8, desugaring, and Kotlin interface default methods.

Note: You need to install the final debug version of the app. Launching it from Studio will install the APK from app\build\intermediates\apk\debug\app-debug.apk which doesn't crash, but the version after doing a Make Project from app\build\outputs\apk\debug\app-debug.apk will.

I don't really see an easy and clean way of fixing this on LeakCanary side. Looks to be a bug in the gradle plugin side. Possibly a separate module that can be manually specified? Not an area that I'm too familiar with.

@pyricau
Copy link
Member

pyricau commented Apr 8, 2022

Thanks for the super detailed answer and the repro!

@pyricau
Copy link
Member

pyricau commented Apr 15, 2022

Since lifecycle 2.5.0 is still in alpha, we should probably see if this is a known issue / if the alphas can be fixed.

@pyricau
Copy link
Member

pyricau commented Apr 15, 2022

@dougnazar do you think you could file an issue on the Lifecycle project?

@dougnazar
Copy link

@sgjesse
Copy link

sgjesse commented May 12, 2022

Seeme like this is caused by a missing dependency on androidx.lifecycle. See https://issuetracker.google.com/230454566#comment4 for details.

@dougnazar
Copy link

I believe this is on purpose. LeakCanary seems to go out of its way to not pull in dependencies that might not be used/wanted. Which was great until this issue popped up.

I'm currently thinking of changing the compileOnly to implementation but removing the androidx module from android-core. Trade off is that it won't pull in androidx automatically but you'd need to specify an additional module if you use androidx.

Not sure which is preferred, or if the LeakCanary devs have a better option.

@dougnazar
Copy link

So this seems to be working for me:

diff --git a/leakcanary-android-core/build.gradle b/leakcanary-android-core/build.gradle
index b13a607a..b8055888 100644
--- a/leakcanary-android-core/build.gradle
+++ b/leakcanary-android-core/build.gradle
@@ -7,7 +7,6 @@ plugins {
 dependencies {
   api projects.sharkAndroid
   api projects.leakcanaryObjectWatcherAndroidCore
-  api projects.leakcanaryObjectWatcherAndroidAndroidx
   api projects.leakcanaryObjectWatcherAndroidSupportFragments
   implementation libs.kotlin.stdlib

diff --git a/leakcanary-object-watcher-android-androidx/build.gradle b/leakcanary-object-watcher-android-androidx/build.gradle
index b979f1bb..26f45de9 100644
--- a/leakcanary-object-watcher-android-androidx/build.gradle
+++ b/leakcanary-object-watcher-android-androidx/build.gradle
@@ -8,8 +8,8 @@ dependencies {
   api projects.leakcanaryObjectWatcherAndroidCore

   implementation libs.kotlin.stdlib
-  // Optional dependency
-  compileOnly libs.androidX.fragment
+  // Required as a runtime dependency so desugaring can add default methods on older APIs
+  implementation libs.androidX.fragment
 }

 android {

and then adding the following to my projects:

    debugImplementation("com.squareup.leakcanary:leakcanary-android:2.10-SNAPSHOT")
    debugImplementation("com.squareup.leakcanary:leakcanary-object-watcher-android-androidx:2.10-SNAPSHOT")

@pyricau
Copy link
Member

pyricau commented May 18, 2022

This is absolutely not the right fix. LeakCanary should not declare an explicit dependency on lifecycle, the whole point of it being optional is that consumers can leverage whichever version they like or even not have that dependency and everything will work just fine. Lifecycle just broke backward compatibility.

@pyricau
Copy link
Member

pyricau commented Jun 10, 2022

Lifecycle 2.5.0-rc02 will include a fix for this: https://android-review.googlesource.com/c/platform/frameworks/support/+/2108693

@pyricau
Copy link
Member

pyricau commented Nov 11, 2022

Closing as this is fixed on the lifecycle side.

@top-master
Copy link

top-master commented Apr 1, 2023

Long story short:

  • Because leak-canary is intentionally using compileOnly for some dependencies,
  • Until the day Android's "desugaring" has better support for said compileOnly,
  • We need to manually find leak-canary's dependencies, duplicate them in each of our projects, and that just to replace compileOnly with implementation.

Example

dependencies {
    // ...

    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$my_lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$my_lifecycle_version"
}

Where my_lifecycle_version should be 2.5.1 (or maybe newer).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants