【问题标题】:ViewModel has no zero argument constructor error - even when it has a zero argument constructorViewModel 没有零参数构造函数错误 - 即使它具有零参数构造函数
【发布时间】:2020-09-26 15:54:45
【问题描述】:

我是 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"
}

原帖

我正在尝试使用 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();
        }
    }

还有一个扩展 ViewModel 以允许主要活动到达 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);

我在该行收到错误:

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

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

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

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

非常感谢您的帮助

【问题讨论】:

  • “还有一个扩展 ViewModel 以允许主要活动到达 LocationLiveData 的类”——我不希望它像 there is no getApplicationContext() method in ViewModel 那样编译。 LocationViewModel 是否可能被声明为其他东西的内部类,比如一个活动,它确实有一个 getApplicationContext() 方法?
  • 感谢@CommonsWare。我用一个不涉及 getApplicationContext() 行的更简单的测试代码编辑了这篇文章,我得到了同样的错误。回复:getApplicationContext,我原来的方法是将上下文传递给 LocationViewModel,但我把它拿出来得到一个零参数的构造函数。除了所述之外,我没有任何课程,这是我迄今为止唯一的活动!
  • @CommonsWare - 想知道您是否可以再提供一条建议。我希望根据用户与给定点的接近程度(在 UI 中动态设置)来改变位置更新的频率。在 onMapReady 中,我正在观察 LocationLiveData。我想我可以有一个 locationRequest LiveData 对象,该对象由我的观察者更新,并且本身在 LocationLiveData 中被观察到;或者我的观察者可以调用 locationViewModel 方法,该方法调用 LocationLiveData 方法以使用一些新参数重新开始更新。知道哪个(如果有的话)更健壮吗?
  • 对不起,我想我不明白你的情况。我建议您提出一个单独的 Stack Overflow 问题,您可以在其中提供更多详细信息。

标签: java android android-livedata android-viewmodel android-fusedlocation


【解决方案1】:

在使用刀柄时我忘记添加时遇到同样的问题

@AndroidEntryPoint

活动声明

【讨论】:

    【解决方案2】:

    要么:

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

    • 使MyViewModel成为static class

    现在,您已将MyViewModel 定义为MainActivity 的内部类。这是行不通的,因为只有MainActivity 的实例可以创建MyViewModel 的实例。特别是,ViewModelProvider 无法创建MyViewModel 的实例。

    【讨论】:

    • 非常感谢,这确实是问题所在!为玩具示例工作,然后经过几次调整后,真实代码也可以工作。正如你所说,一旦我将 LocationViewModel 设为静态类,getApplicationContext() 就不起作用了,所以我给 LocationViewModel 一个名为 setContext 的方法,在主代码中我可以将应用程序上下文传递给它(以防这对任何人都有用)。
    • 您也可以切换回AndroidViewModel,它可以处理您需要Context 的情况。特别是,它会强制您将Application 用作Context,从而防止您不小心将Activity 用作Context 并导致内存泄漏。但是,无论如何,我很高兴它对你有用!
    【解决方案3】:

    当你写作时

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

    这使得MyViewModel 成为MainActivity 的内部类,这意味着它具有对外部类的隐式引用(根据Java documentation)并且不能与MainActivity 分开构造。这实际上意味着在字节码中,它的构造函数总是采用 MainActivity 的实例——即使你没有写出那个构造函数。

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

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

    【讨论】:

    • 谢谢,让 MyViewModel 成为一个静态类解决了这个问题。我真的不知道 static 关键字是什么意思,所以感谢您的解释!
    【解决方案4】:

    在我的情况下确实忘记添加 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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-26
      • 1970-01-01
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 2023-01-02
      相关资源
      最近更新 更多