英文:
ViewModel instance - Activity UI - Android Architecture Components
问题
以下是您提供的代码的中文翻译:
public class WordViewModel extends AndroidViewModel {
private WordRepository mRepository;
private LiveData<List<Word>> mAllWords;
public WordViewModel(@NonNull Application application) {
super(application);
mRepository = new WordRepository(application);
mAllWords = mRepository.getAllWords();
}
LiveData<List<Word>> getAllWords() {
return mAllWords;
}
public void insert(Word word) {
mRepository.insert(word);
}
}
mWordViewModel = new ViewModelProvider(this,
new ViewModelProvider.AndroidViewModelFactory(getApplication()))
.get(WordViewModel.class);
public class WordRepository {
private WordDao mWordDao;
private LiveData<List<Word>> mAllWords;
public WordRepository(Application application) {
WordRoomDatabase db = WordRoomDatabase.getDatabase(application);
mWordDao = db.wordDao();
mAllWords = mWordDao.getAllWords();
}
LiveData<List<Word>> getAllWords() {
return mAllWords;
}
public void insert(Word word) {
new insertAsyncTask(mWordDao).execute(word);
}
private static class insertAsyncTask extends AsyncTask<Word, Void, Void> {
private WordDao mAsyncTaskDao;
insertAsyncTask(WordDao dao) {
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(final Word... params) {
mAsyncTaskDao.insert(params[0]);
return null;
}
}
}
@Database(entities = {Word.class}, version = 1, exportSchema = false)
public abstract class WordRoomDatabase extends RoomDatabase {
public abstract WordDao wordDao();
private static WordRoomDatabase INSTANCE;
public static WordRoomDatabase getDatabase(Context context) {
if (INSTANCE == null) {
synchronized (WordRoomDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}
}
}
return INSTANCE;
}
private static Callback sRoomDatabaseCallback =
new Callback() {
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
new PopulateDbAsync(INSTANCE).execute();
}
};
/**
* 在后台填充数据库。
*/
private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
private final WordDao mDao;
String[] words = {"dolphin", "crocodile", "cobra"};
PopulateDbAsync(WordRoomDatabase db) {
mDao = db.wordDao();
}
@Override
protected Void doInBackground(final Void... params) {
// 每次启动应用程序时都使用空数据库。
// 如果只在首次创建数据库时填充数据库,则不需要这样做
mDao.deleteAll();
for (int i = 0; i <= words.length - 1; i++) {
Word word = new Word(words[i]);
mDao.insert(word);
}
return null;
}
}
}
我明白您遇到了一个错误,但您没有提供足够的信息来解决问题。如果您需要帮助,可以提供更多关于错误的详细信息,我将尽力协助您。
英文:
public class WordViewModel extends AndroidViewModel {
private WordRepository mRepository;
private LiveData<List<Word>> mAllWords;
public WordViewModel(@NonNull Application application) {
super(application);
mRepository = new WordRepository(application);
mAllWords = mRepository.getAllWords();
}
LiveData<List<Word>> getAllWords() {
return mAllWords;
}
public void insert(Word word) {
mRepository.insert(word);
}
}
mWordViewModel = new ViewModelProvider(this,
new ViewModelProvider.AndroidViewModelFactory(getApplication()))
.get(WordViewModel.class);
public class WordRepository {
private WordDao mWordDao;
private LiveData<List<Word>> mAllWords;
public WordRepository(Application application) {
WordRoomDatabase db = WordRoomDatabase.getDatabase(application);
mWordDao = db.wordDao();
mAllWords = mWordDao.getAllWords();
}
LiveData<List<Word>> getAllWords() {
return mAllWords;
}
public void insert(Word word) {
new insertAsyncTask(mWordDao).execute(word);
}
private static class insertAsyncTask extends AsyncTask<Word, Void, Void> {
private WordDao mAsyncTaskDao;
insertAsyncTask(WordDao dao) {
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(final Word... params) {
mAsyncTaskDao.insert(params[0]);
return null;
}
}
}
@Database(entities = {Word.class}, version = 1, exportSchema = false)
public abstract class WordRoomDatabase extends RoomDatabase {
public abstract WordDao wordDao();
private static WordRoomDatabase INSTANCE;
public static WordRoomDatabase getDatabase(Context context) {
if (INSTANCE == null) {
synchronized (WordRoomDatabase.class) {
if (INSTANCE == null) {
Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}
}
}
return INSTANCE;
}
private static Callback sRoomDatabaseCallback =
new Callback() {
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
new PopulateDbAsync(INSTANCE).execute();
}
};
/**
* Populate the database in the background.
*/
private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
private final WordDao mDao;
String[] words = {"dolphin", "crocodile", "cobra"};
PopulateDbAsync(WordRoomDatabase db) {
mDao = db.wordDao();
}
@Override
protected Void doInBackground(final Void... params) {
// Start the app with a clean database every time.
// Not needed if you only populate the database
// when it is first created
mDao.deleteAll();
for (int i = 0; i <= words.length - 1; i++) {
Word word = new Word(words[i]);
mDao.insert(word);
}
return null;
}
}
}
I am trying to instantiate ViewModel class in my MainActivity's onCreate method but it shows the following error.
Cannot create an instance of class com.example.roomwords_sample.WordViewModel
I also tried using ViewModelProviders.of(this).get(ViewModel.class) but it is still showing the same error. I also looking at other people's answers on similar question but it is not working. I have tried almost everything. Kindly help me out.
Added stack trace
2020-09-20 01:51:37.103 13578-13578/com.example.roomwords_sample E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.roomwords_sample, PID: 13578
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.roomwords_sample/com.example.roomwords_sample.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.roomwords_sample.WordViewModel
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.roomwords_sample.WordViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:275)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.example.roomwords_sample.MainActivity.onCreate(MainActivity.java:32)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:223) 
at android.app.ActivityThread.main(ActivityThread.java:7656) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) 
at com.example.roomwords_sample.MainActivity.onCreate(MainActivity.java:32) 
at android.app.Activity.performCreate(Activity.java:8000) 
at android.app.Activity.performCreate(Activity.java:7984) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:223) 
at android.app.ActivityThread.main(ActivityThread.java:7656) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'com.example.roomwords_sample.WordDao com.example.roomwords_sample.WordRoomDatabase.wordDao()' on a null object reference
at com.example.roomwords_sample.WordRepository.<init>(WordRepository.java:18)
at com.example.roomwords_sample.WordViewModel.<init>(WordViewModel.java:18)
at java.lang.reflect.Constructor.newInstance0(Native Method) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:343) 
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) 
at com.example.roomwords_sample.MainActivity.onCreate(MainActivity.java:32) 
at android.app.Activity.performCreate(Activity.java:8000) 
at android.app.Activity.performCreate(Activity.java:7984) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:223) 
at android.app.ActivityThread.main(ActivityThread.java:7656) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
答案1
得分: 1
问题出在你的 WordRoomDatabase.getDatabase(application)
方法中。
当你写下:
if (INSTANCE == null) {
Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}
你创建了数据库,但实际上没有将它分配给你的 INSTANCE
变量。这意味着你的 INSTANCE
始终为 null,而 WordRoomDatabase.getDatabase(application)
从不返回除了 null 之外的任何内容。
你可以通过设置你的 INSTANCE
变量来解决这个问题和由此引发的 NullPointerException
:
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}
英文:
The problem is with your WordRoomDatabase.getDatabase(application)
method
When you write:
if (INSTANCE == null) {
Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}
You create the database, but you don't actually assign it to your INSTANCE
variable. That means your INSTANCE
is always null and WordRoomDatabase.getDatabase(application)
never actually returns anything but null.
You can fix your issue and the NullPointerException
that comes from it by setting your INSTANCE
variable:
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
WordRoomDatabase.class, "word_database")
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论