ViewModel 没有零参数构造函数错误 - 即使它具有零参数构造函数
ViewModel has no zero argument constructor error - even when it has a zero argument constructor
我是 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);
}
}
我得到了同样的错误。这是我的应用程序级别 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"
}
原版POST
我正在尝试使用 ViewModel 和 LiveData 来更新用户位置,据我所知,这是了解生命周期的最佳方式。我有一个默认地图 activity...
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {...}
扩展 LiveData 以存储用户位置的 class...
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();
}
}
还有一个 class 扩展 ViewModel 以允许主要 activity 到达 LocationLiveData。
public class LocationViewModel extends ViewModel {
private LocationLiveData locationLiveData;
public LocationViewModel () {
locationLiveData = new LocationLiveData(getApplicationContext());
}
public LocationLiveData getLocationLiveData() {
return locationLiveData;
}
}
然后当我尝试在 onMapReady 方法中创建 locationViewModel 的实例时:
LocationViewModel locationViewModel = new ViewModelProvider(this).get(LocationViewModel.class);
我在该行收到错误:
Cannot create an instance of class com.example.MapsActivity$LocationViewModel
Caused by: java.lang.InstantiationException: java.lang.Class has no zero argument constructor
即使我完全在 locationViewModel 中取出构造函数,并且如果我尝试扩展 AndroidViewModel,我也会收到此错误。
有什么想法吗?我见过其他类似的查询,但答案始终是从构造函数中取出参数——我已经这样做了!
非常感谢您的帮助
或者:
将 MyViewModel
移动到单独的 Java 文件,或
使 MyViewModel
成为 static class
现在,您已将 MyViewModel
定义为 MainActivity
的内部 class。这是行不通的,因为只有 MainActivity
的实例才能创建 MyViewModel
的实例。特别是,ViewModelProvider
无法创建 MyViewModel
.
的实例
写的时候
public class MainActivity extends AppCompatActivity {
public class MyViewModel extends ViewModel {
public int scoreTeamA = 0;
}
}
这使得 MyViewModel
成为 MainActivity
的内部 class,这意味着它具有对外部 class 的隐式引用(根据 Java documentation)并且不能与 MainActivity
分开构造。这实际上意味着在字节码中,它的构造函数总是采用 MainActivity
的实例——即使你没有写出那个构造函数。
您可以通过添加 static
关键字使内部 class 成为静态嵌套 class。这删除了对外部 class 的隐式引用,并使其类似于任何其他顶级 class:
public class MainActivity extends AppCompatActivity {
public static class MyViewModel extends ViewModel {
public int scoreTeamA = 0;
}
}
while using hilt I am facing the same issue when I forgot to add
@AndroidEntryPoint
在 activity 声明上方
在我的例子中忘记添加
HasSupportFragmentInjector
我的 Activity
!!!
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;
}
}
我是 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);
}
}
我得到了同样的错误。这是我的应用程序级别 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"
}
原版POST
我正在尝试使用 ViewModel 和 LiveData 来更新用户位置,据我所知,这是了解生命周期的最佳方式。我有一个默认地图 activity...
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {...}
扩展 LiveData 以存储用户位置的 class...
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();
}
}
还有一个 class 扩展 ViewModel 以允许主要 activity 到达 LocationLiveData。
public class LocationViewModel extends ViewModel {
private LocationLiveData locationLiveData;
public LocationViewModel () {
locationLiveData = new LocationLiveData(getApplicationContext());
}
public LocationLiveData getLocationLiveData() {
return locationLiveData;
}
}
然后当我尝试在 onMapReady 方法中创建 locationViewModel 的实例时:
LocationViewModel locationViewModel = new ViewModelProvider(this).get(LocationViewModel.class);
我在该行收到错误:
Cannot create an instance of class com.example.MapsActivity$LocationViewModel
Caused by: java.lang.InstantiationException: java.lang.Class has no zero argument constructor
即使我完全在 locationViewModel 中取出构造函数,并且如果我尝试扩展 AndroidViewModel,我也会收到此错误。
有什么想法吗?我见过其他类似的查询,但答案始终是从构造函数中取出参数——我已经这样做了!
非常感谢您的帮助
或者:
将
MyViewModel
移动到单独的 Java 文件,或使
MyViewModel
成为static class
现在,您已将 MyViewModel
定义为 MainActivity
的内部 class。这是行不通的,因为只有 MainActivity
的实例才能创建 MyViewModel
的实例。特别是,ViewModelProvider
无法创建 MyViewModel
.
写的时候
public class MainActivity extends AppCompatActivity {
public class MyViewModel extends ViewModel {
public int scoreTeamA = 0;
}
}
这使得 MyViewModel
成为 MainActivity
的内部 class,这意味着它具有对外部 class 的隐式引用(根据 Java documentation)并且不能与 MainActivity
分开构造。这实际上意味着在字节码中,它的构造函数总是采用 MainActivity
的实例——即使你没有写出那个构造函数。
您可以通过添加 static
关键字使内部 class 成为静态嵌套 class。这删除了对外部 class 的隐式引用,并使其类似于任何其他顶级 class:
public class MainActivity extends AppCompatActivity {
public static class MyViewModel extends ViewModel {
public int scoreTeamA = 0;
}
}
while using hilt I am facing the same issue when I forgot to add
@AndroidEntryPoint
在 activity 声明上方
在我的例子中忘记添加
HasSupportFragmentInjector
我的 Activity
!!!
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;
}
}