I'm new to Android and Java and am trying to make a location-based app.
EDIT
I've made a much, much simpler test code and get the same error. Here's the 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);
}
}
I get the same error. Here are the dependencies in 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"
}
ORIGINAL POST
I'm attempting to use ViewModel and LiveData to update the user location as I understand that's the best way to be lifecycle-aware. I have a default maps activity...
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {...}
A class which extends LiveData to store the user location...
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();
}
}
And a class which extends ViewModel to allow the main activity to reach the LocationLiveData.
public class LocationViewModel extends ViewModel {
private LocationLiveData locationLiveData;
public LocationViewModel () {
locationLiveData = new LocationLiveData(getApplicationContext());
}
public LocationLiveData getLocationLiveData() {
return locationLiveData;
}
}
Then when I attempt to make an instance of locationViewModel in the onMapReady method:
LocationViewModel locationViewModel = new ViewModelProvider(this).get(LocationViewModel.class);
I get an error on that line:
Cannot create an instance of class com.example.MapsActivity$LocationViewModel
Caused by: java.lang.InstantiationException: java.lang.Class has no zero argument constructor
I get this error even if I take out the constructor entirely in locationViewModel, and also if I attempt to extend AndroidViewModel instead.
Any ideas? I've seen other similar queries but the answer has always been to take arguments out of the constructor - which I've already done!
Thanks a lot for any help
Either:
Move MyViewModel
to a separate Java file, or
Make MyViewModel
be a static class
Right now, you have defined MyViewModel
as an inner class of MainActivity
. That will not work, as only an instance of MainActivity
can create an instance of MyViewModel
. In particular, ViewModelProvider
cannot create an instance of MyViewModel
.