Java ViewModel没有零参数构造函数错误-即使它有零参数构造函数

Java ViewModel没有零参数构造函数错误-即使它有零参数构造函数,java,android,android-livedata,android-viewmodel,android-fusedlocation,Java,Android,Android Livedata,Android Viewmodel,Android Fusedlocation,我是Android和Java新手,正在尝试制作一款基于位置的应用程序 编辑 我做了一个非常简单的测试代码,得到了同样的错误。以下是java: package com.example.viewmodeltest; import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; import andr

我是Android和Java新手,正在尝试制作一款基于位置的应用程序

编辑

我做了一个非常简单的测试代码,得到了同样的错误。以下是java:

package com.example.viewmodeltest;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    public class MyViewModel extends ViewModel {
        public int scoreTeamA = 0;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyViewModel locationViewModel = new ViewModelProvider(this).get(MyViewModel.class);
    }
}
我也犯了同样的错误。以下是my app level build.gradle中的依赖项:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    //dependencies for ViewModel, LiveData, etc.
    def lifecycle_version = "2.2.0"
    def arch_version = "2.1.0"

    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
    // Lifecycles only (without ViewModel or LiveData)
    implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
    // Saved state module for ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
    // Annotation processor
    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
}
原创帖子

我试图使用ViewModel和LiveData来更新用户位置,因为我知道这是了解生命周期的最佳方式。我有一个默认的“地图”活动

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {...}
扩展LiveData以存储用户位置的类

public class LocationLiveData extends LiveData<Location> {
        private final Context context;
        private FusedLocationProviderClient fusedLocationClient;
        private LocationRequest locationRequest;

        public LocationLiveData(Context context) {
            this.context = context;
            this.fusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
        }

        private void setLocationData(Location location) {
            Location value = new Location("SetInternal");
            value.setLatitude(location.getLatitude());
            value.setLongitude(location.getLongitude());
            setValue(value);
        }

        protected void createLocationRequest() {
            LocationRequest locationRequest = LocationRequest.create();
            locationRequest.setInterval(1000);
            locationRequest.setFastestInterval(500);
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        }

        private LocationCallback locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                if (locationResult == null) {
                    return;
                }
                for (Location location : locationResult.getLocations()) {
                    setLocationData(location);
                }
            }
        };

        private void startLocationUpdates() {
            createLocationRequest();
            fusedLocationClient.requestLocationUpdates(locationRequest,
                    locationCallback,
                    Looper.getMainLooper());
        }

        @Override
        protected void onInactive() {
            super.onInactive();
            fusedLocationClient.removeLocationUpdates(locationCallback);
        }

        @Override
        protected void onActive() {
            super.onActive();
            fusedLocationClient.getLastLocation()
                    .addOnSuccessListener(new OnSuccessListener<Location>() {
                        @Override
                        public void onSuccess(Location location) {
                            if (location != null)
                                setValue(location);
                        }
                    });
            startLocationUpdates();
        }
    }
然后,当我尝试在onMapReady方法中创建locationViewModel的实例时:

LocationViewModel locationViewModel = new ViewModelProvider(this).get(LocationViewModel.class);
我在那一行得到一个错误:

无法创建com.example.MapsActivity$LocationViewModel类的实例

原因:java.lang.InstanceException:java.lang.Class没有零参数构造函数

即使我完全在locationViewModel中取出构造函数,并且尝试扩展AndroidViewModel,我也会出现此错误

有什么想法吗?我见过其他类似的查询,但答案总是从构造函数中取出参数——我已经这样做了

非常感谢您的帮助

或者:

  • MyViewModel
    移动到单独的Java文件,或

  • 使
    MyViewModel
    成为
    静态类

现在,您已经将
MyViewModel
定义为
MainActivity
的一个内部类。这将不起作用,因为只有
MainActivity
的实例才能创建
MyViewModel
的实例。特别是,
ViewModelProvider
在编写时无法创建
MyViewModel

的实例

public class MainActivity extends AppCompatActivity {

    public class MyViewModel extends ViewModel {
       public int scoreTeamA = 0;
    }
}
这使得
MyViewModel
成为
MainActivity
的内部类,这意味着它有一个对外部类的隐式引用(根据),并且不能与
MainActivity
分开构造。这实际上意味着在字节码中,它的构造函数总是以
MainActivity
为实例,即使您没有写出该构造函数

通过添加
static
关键字,可以使内部类成为静态嵌套类。这将删除对外部类的隐式引用,并使其与任何其他顶级类类似:

public class MainActivity extends AppCompatActivity {

    public static class MyViewModel extends ViewModel {
       public int scoreTeamA = 0;
    }
}
使用刀柄时,我遇到了同样的问题,因为我忘了添加


上面的活动声明

在我的情况下,我忘了添加
HasSupportFragmentInjector
到我的
活动

public class MainActivity extends AppComaptActivity
        implements HasSupportFragmentInjector{


@Override
public void onCreate(Bundle savedInstanceState) {
    AndroidInjection.inject(this);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    @Inject
    DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector;


    @Override
    public AndroidInjector<Fragment> supportFragmentInjector() {
        return fragmentDispatchingAndroidInjector;
    }
}
public class main活动扩展了AppComaptActivity
机具HasSupportFragmentInjector{
@凌驾
创建时的公共void(Bundle savedInstanceState){
雄激素注射。注射(此);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
@注入
分派ANDROID注入器碎片分派ANDROID注入器;
@凌驾
公共雄激素注射器支持碎片注射器(){
返回碎片分派和重新分配;
}
}

“以及一个扩展ViewModel以允许主活动访问LocationLiveData的类”--我不希望编译它,因为.Is
LocationViewModel
可能声明为具有
getApplicationContext()的其他内容(如活动)的内部类
method?谢谢@commonware。我用一个更简单的测试代码编辑了这篇文章,它不涉及getApplicationContext()Re:getApplicationContext,我最初的方法是将一个上下文传递到LocationViewModel中,但我将其取出以获得一个零参数构造函数。除了声明的类之外,我没有任何类,这是我目前为止唯一的活动!@Commonware-想知道您是否可以提供更多的ad我希望根据用户离给定点的距离来改变位置更新的频率(在UI中动态设置)。在onMapReady中,我正在观察LocationLiveData。我想我可以拥有一个locationRequest LiveData对象,该对象由我的oberver更新,并在LocationLiveData中观察到;或者我的观察者可以调用locationViewModel方法,该方法调用LocationLiveData方法,以使用一些新参数重新启动更新。你有什么想法h(如有)是否更健壮?抱歉,但我想我不理解您的情况。我建议您提出一个单独的堆栈溢出问题,从中可以提供更多详细信息。非常感谢,这确实是问题所在!适用于玩具示例,经过几次调整后,真正的代码也起作用了。正如您所说,getApplicationContext()一旦我将LocationViewModel设置为静态类,它就无法工作,因此我给LocationViewModel一个名为setContext的方法,在主代码中,我可以将应用程序上下文传递给它(以防这对任何人都有用)。您还可以切换回
AndroidViewModel
,它处理您需要
上下文的情况。特别是,它强制您将
应用程序
用作
上下文
,防止您意外地将
活动
用作
上下文
,并导致内存泄漏。但是,请注意少一点,我很高兴它能为你工作!谢谢,使MyViewModel成为一个静态类解决了这个问题。我真的不知道静态关键字是什么意思,所以谢谢你的解释!
@AndroidEntryPoint
public class MainActivity extends AppComaptActivity
        implements HasSupportFragmentInjector{


@Override
public void onCreate(Bundle savedInstanceState) {
    AndroidInjection.inject(this);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    @Inject
    DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector;


    @Override
    public AndroidInjector<Fragment> supportFragmentInjector() {
        return fragmentDispatchingAndroidInjector;
    }
}