Recently I wrote a simple Android App.
The App has a simple MainActivity and a ViewModel. While writing the code I did declare the ViewModel class to be public.
Just before I finished the app I went over warnings and saw one saying that the access modifier of the ViewModel class can become package instead of public.
At the time I did not give it much thought and removed the public modifier.
I tested the app and everything worked fine.
I then made a release build and the app crashed upon startup. I did not make the connection to why this happened but from a quick look at the stack trace, I got it. I added the public modifier back to the ViewModel class and everything was working as it should.
Since the ViewModel is actually instantiated by the provider that is outside of my package the ViewModel have to have a public modifier.
My question is why did my app work properly in Debug compilation configuration as I would expect it to crash there too...
My ViewModel:
import android.app.Application;
import android.util.Log;
import androidx.lifecycle.AndroidViewModel;
import java.util.ArrayList;
import java.util.Random;
public class TilesViewModel extends AndroidViewModel {
My createtion of the ViewModel:
mViewModel = ViewModelProviders.of(this).get(TilesViewModel.class);
Crash:
Caused by: java.lang.RuntimeException: Cannot create an instance of class il.co.woo.karuba.TilesViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:234)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:164)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:130)
at il.co.woo.karuba.MainActivity.onCreate(MainActivity.java:70)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.IllegalAccessException: java.lang.Class<il.co.woo.karuba.TilesViewModel> is not accessible from java.lang.Class<androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory>
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:230)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:164)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:130)
at il.co.woo.karuba.MainActivity.onCreate(MainActivity.java:70)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)