由于Java访问修饰符而导致应用崩溃-为什么?

时间:2019-07-15 06:53:15

标签: java android android-lifecycle

最近我写了一个简单的Android应用程序。

该应用程序具有一个简单的MainActivity和一个ViewModel。 在编写代码时,我确实声明ViewModel类是公共的。

就在我完成该应用程序之前,我浏览了警告,并看到一个说法,即ViewModel类的access修饰符可以变为包而不是public。

当时我没有考虑太多,因此删除了公共修饰符。

我测试了该应用,一切正常。

然后我做了一个发布版本,该应用程序在启动时崩溃了。我没有联系到发生这种情况的原因,但是通过快速查看堆栈跟踪,我知道了。 我将public修饰符添加回ViewModel类,一切都按预期进行。

由于ViewModel实际上是由我的包之外的提供程序实例化的,因此ViewModel必须具有公共修饰符。

我的问题是为什么我的应用程序在Debug编译配置中能正常运行,因为我希望它也会在那里崩溃...

我的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 {

我对ViewModel的创建:

mViewModel = ViewModelProviders.of(this).get(TilesViewModel.class);

崩溃:

 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) 

1 个答案:

答案 0 :(得分:0)

例如,与创建ViewModel有关的原因很多。

  1. 您没有为类或构造函数使用公共访问修饰符,并且工厂可能无法创建它的实例。
  2. 您扩展了错误的ViewModel
  3. 由于无法在构造函数中创建其他注入的对象,因此,ViewModel参数化的构造函数也可能会产生问题。

但是对于您来说,在 Debug (调试)而不是 Release (正常发布)中工作的原因可能是 Proguard 可能会截断访问修饰符或未使用的构造函数,可能会导致此问题。

Reference discussion