创建类viewModel

时间:2018-06-20 06:59:36

标签: android android-room android-viewmodel

我只是想学习Room。因此,我根据Google在this中提供的指南创建了一个示例应用程序。我收到以下错误

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.brahma/com.brahma.ui.SignUpActivity}: java.lang.RuntimeException: Cannot create an instance of class com.brahma.viewModel.UserViewModel
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6501)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
     Caused by: java.lang.RuntimeException: Cannot create an instance of class com.brahma.viewModel.UserViewModel
        at android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:207)
        at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134)
        at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102)
        at com.brahma.ui.SignUpActivity.onCreate(SignUpActivity.java:72)
        at android.app.Activity.performCreate(Activity.java:7036)
        at android.app.Activity.performCreate(Activity.java:7027)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6501) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
        at android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:199)
        at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134) 
        at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102) 
        at com.brahma.ui.SignUpActivity.onCreate(SignUpActivity.java:72) 
        at android.app.Activity.performCreate(Activity.java:7036) 
        at android.app.Activity.performCreate(Activity.java:7027) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6501) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 
     Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
        at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:164)
        at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:192)
        at com.brahma.Room.UserDao_Impl.getUser(UserDao_Impl.java:56)
        at com.brahma.repository.UserRepository.<init>(UserRepository.java:18)
        at com.brahma.viewModel.UserViewModel.<init>(UserViewModel.java:17)
        at java.lang.reflect.Constructor.newInstance0(Native Method) 
        at java.lang.reflect.Constructor.newInstance(Constructor.java:334) 
        at android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:199) 
        at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134) 
        at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102) 
        at com.brahma.ui.SignUpActivity.onCreate(SignUpActivity.java:72) 
        at android.app.Activity.performCreate(Activity.java:7036) 
        at android.app.Activity.performCreate(Activity.java:7027) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1215) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6501) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 

我试图在Internet上寻找解决方案,但没有成功。 stackOverflow上可用的解决方案要求将构造函数公开给viewModel,而我的构造函数已经是该模型。

这是我的viewModel:

public class UserViewModel extends AndroidViewModel{

    private UserRepository mUserRepository;
    private User mUserInfo;

    public UserViewModel( Application application) {
        super(application);
        mUserRepository = new UserRepository(application);
        mUserInfo = mUserRepository.getmUserInfo();
    }


    public User getUserInfo(){
        return mUserInfo;
    }
    public void insert(User user){
        mUserRepository.insert(user);
    }
}

以下是我实例化viewModel的活动:

protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FacebookSdk.sdkInitialize(getApplicationContext());
        setContentView(R.layout.activity_sign_up);
        AppEventsLogger.activateApp(this, getString(R.string.facebook_app_id));
        initViews();

        mUserViewModel = ViewModelProviders.of(this).get(UserViewModel.class);

        callbackManager = CallbackManager.Factory.create();
        mGoogleSignUp.setOnClickListener(this);
        mFacebookSignUp.setOnClickListener(this);
        initGoogleApiClient();
    }

我不知道我在做什么错

3 个答案:

答案 0 :(得分:0)

正如它在靠近底部的调用堆栈中所说的那样,您正在主线程上调用数据库查询。

 Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

有了Room,您不能在UI线程上发出请求,我相信是因为这一行。

mUserInfo = mUserRepository.getmUserInfo();

如果您使用的是Room和ViewModels,只需使用LiveData。最终产品也将更容易使用。

答案 1 :(得分:0)

我刚刚找到了解决问题的方法。

用于创建viewModel类的新实例的ViewModelProvider始终调用默认构造函数。因为在我的应用程序中,我没有声明默认构造函数,所以它会向我抛出错误“ 无法创建类ViewModel的实例”。因此,您必须在ViewModel类中创建一个默认构造函数。

如果您不想创建默认的构造函数或想要像我一样创建其他构造函数,则必须创建一个视图模型提供程序工厂。

Here,您可以提供一个示例如何为viewModel创建工厂类。

希望此解决方案可以帮助您更好地理解ViewModel。

答案 2 :(得分:0)

问题是您正在尝试在主线程上运行查询。 您可以通过两种方式解决此问题:

1。在您的存储库类中,使用mUserRepository.getmUserInfo()内的Asynctask来获取类型列表或用户类型的数据。将解决您的问题。

2。调用allowMainThreadQueries()将解决此问题。 您需要像这样在RoomDatabase实例中调用allowMainThreadQueries()

//where INSTANCE is of type Database
    public static Database getDatabase(final Context context) {
        if (INSTANCE == null) {
            synchronized (Database.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                            Database.class, DATABASE_NAME)
                            // Wipes and rebuilds instead of migrating if no Migration object.
                            // Migration is not part of this codelab.
                            .fallbackToDestructiveMigration()
                            //allows queries to execute on main thread
                            .allowMainThreadQueries()
                            //.addCallback(sRoomDatabaseCallback)
                            .build();

                }
            }
        }
        return INSTANCE;
    }