본문 바로가기

컴퓨터

ViewModel에 0 인수 생성자 오류가 없습니다-인수 생성자가 0 인 경우에도

저는 Android와 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"

}
원래 포스트

ViewModel 및 LiveData를 사용하여 사용자 위치를 업데이트하려고합니다. 이것이 수명주기를 인식하는 가장 좋은 방법이라는 것을 알고 있습니다. 기본지도 활동이 있습니다 ...

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {...}
사용자 위치를 저장하기 위해 LiveData를 확장하는 클래스 ...

public class LocationLiveData extends LiveData {
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();
    }
}

그리고 메인 액티비티가 LocationLiveData에 도달 할 수 있도록 ViewModel을 확장하는 클래스입니다.

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);
해당 줄에 오류가 발생합니다.

com.example.MapsActivity $ LocationViewModel 클래스의 인스턴스를 만들 수 없습니다.

원인 : java.lang.InstantiationException : java.lang.Class에 0 인수 생성자가 없습니다.

locationViewModel에서 생성자를 완전히 제거하고 대신 AndroidViewModel을 확장하려고해도이 오류가 발생합니다.

어떤 아이디어? 나는 다른 유사한 쿼리를 보았지만 대답은 항상 생성자에서 인수를 꺼내는 것이 었습니다.

도움을 주셔서 감사합니다

자바
기계적 인조 인간
android-livedata
android-viewmodel
안드로이드 융합 위치
공유 이 질문을 개선 따르다
생성 7 jun. 17:55:14
생성 7 jun. 17:40:28

Jaber
1831은색 배지 1 개10브론즈 배지 10 개
1
"그리고 뷰 모델을 확장하는 클래스의 주요 활동이 LocationLiveData에 도달 할 수 있도록하는"- 나는, 즉 컴파일 기대하지 않을 것이다 전혀 없다 getApplicationContext()의 방법ViewModel . 되어 LocationViewModel아마도 가지고 활동과 같은 다른 뭔가의 내부 클래스로 선언 getApplicationContext()하는 방법을? – CommonsWare 6 월 7 일 17:44
감사합니다 @ CommonsWare. getApplicationContext () 줄을 포함하지 않는보다 간단한 테스트 코드로 게시물을 편집했는데 동일한 오류가 발생합니다. 다시 : getApplicationContext, 내 원래 접근 방식은 대신 LocationViewModel에 컨텍스트를 전달하는 것이었지만 인수가 0 인 생성자를 얻기 위해 이것을 제거했습니다. 명시된 것 외에 다른 수업이 없으며 이것이 지금까지 유일한 활동입니다! – Jaber 6 월 7 일 17:59
@CommonsWare-한 가지 더 많은 조언을 제공 할 수 있는지 궁금합니다. 사용자가 주어진 지점에 얼마나 가까운 지 (UI에서 동적으로 설정 됨)에 따라 위치 업데이트 빈도를 변경하려고합니다. onMapReady에서 LocationLiveData를 관찰하고 있습니다. 내 oberver에 의해 업데이트되고 LocationLiveData 내에서 자체적으로 관찰되는 locationRequest LiveData 객체를 가질 수 있다고 생각했습니다. 또는 내 관찰자는 LocationLiveData 메서드를 호출하여 일부 새 매개 변수로 업데이트를 다시 시작하는 locationViewModel 메서드를 호출 할 수 있습니다. 어느 쪽이 더 강력한 지 아십니까? – Jaber 6 월 12 일 12:15
죄송합니다. 귀하의 상황을 이해하지 못하는 것 같습니다. 자세한 내용을 제공 할 수있는 별도의 Stack Overflow 질문을하는 것이 좋습니다. – CommonsWare 6 월 12 일 12:24
의견을 추가하다
4 개의 답변

2

어느 한 쪽:

MyViewModel별도의 Java 파일로 이동 하거나

만들기 MyViewModel가 수static class

지금 MyViewModel은 내부 클래스로 정의 했습니다 MainActivity. 의 인스턴스 만의 인스턴스를 MainActivity만들 수 있으므로 작동하지 않습니다 MyViewModel. 특히 ViewModelProvider의 인스턴스를 만들 수 없습니다 MyViewModel.

공유 이 답변을 개선 따르다
생성 7 jun. 18:02:22

CommonsWare
881k161골드 배지 161 개21542154 실버 배지21802180 브론즈 배지
정말 감사합니다. 이것이 실제로 문제였습니다! 장난감 예제에서 작업 한 다음 몇 가지 조정 후에 실제 코드도 작동했습니다. 말했듯이 getApplicationContext ()는 LocationViewModel을 정적 클래스로 만들었을 때 작동하지 않았으므로 LocationViewModel에 setContext라는 메서드를 제공했습니다. 주 코드에서 응용 프로그램 컨텍스트를 전달할 수 있습니다 (누구에게나 유용 할 경우 ). – Jaber 6 월 8 일 0:04
으로 다시 전환 할 수도 있습니다. AndroidViewModel이 경우 Context. 특히, 당신은을 사용하도록 강제 Application는 AS Context실수로 사용에서 당신을 방지 Activity는 AS를 Context하고 메모리 누수의 원인. 그러나 어쨌든 당신을 위해 일하는 것이 기쁩니다! – CommonsWare 6 월 8 일 0:11
의견을 추가하다

당신이 쓸 때

public class MainActivity extends AppCompatActivity {

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

}
이것은 MyViewModel내부 클래스를 만듭니다 . MainActivity즉, 외부 클래스에 대한 암시 적 참조 ( Java 문서에 따라 )가 있고 MainActivity. 이것은 효과적으로 바이트 코드에서 생성자를 MainActivity작성하지 않더라도 생성자가 항상 인스턴스를 취한다는 것을 의미합니다 .

static키워드 를 추가하여 내부 클래스를 정적 ​​중첩 클래스로 만들 수 있습니다 . 이렇게하면 외부 클래스에 대한 암시 적 참조가 제거되고 다른 최상위 클래스와 비슷해집니다.

public class MainActivity extends AppCompatActivity {

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

}
공유 이 답변을 개선 따르다
생성 7 jun. 18:03:22

Ianhanniballake
144k16골드 배지 16 개321은색 배지 321 개331브론즈 배지 331 개
감사합니다. MyViewModel을 정적 클래스로 만들어 문제를 해결했습니다. 나는 static 키워드가 무엇을 의미하는지 정말로 몰랐기 때문에 설명해 주셔서 감사합니다! – Jaber 6 월 8 일 0:07
의견을 추가하다

1

칼자루를 사용하는 동안 추가하는 것을 잊었을 때 동일한 문제가 발생합니다.

@AndroidEntryPoint
활동 선언 위에

공유 이 답변을 개선 따르다
생성 29 aug. 21:33:28

AndroidGeek
29.7k11골드 배지 11 개199은색 배지 199 개253브론즈 배지 253 개
의견을 추가하다

0

내 경우에는 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;
}

}