ViewModel实例 – Activity UI – Android架构组件

huangapple go评论52阅读模式
英文:

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&lt;List&lt;Word&gt;&gt; mAllWords;
public WordViewModel(@NonNull Application application) {
super(application);
mRepository = new WordRepository(application);
mAllWords = mRepository.getAllWords();
}
LiveData&lt;List&lt;Word&gt;&gt; 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&lt;List&lt;Word&gt;&gt; mAllWords;
public WordRepository(Application application) {
WordRoomDatabase db = WordRoomDatabase.getDatabase(application);
mWordDao = db.wordDao();
mAllWords = mWordDao.getAllWords();
}
LiveData&lt;List&lt;Word&gt;&gt; getAllWords() {
return mAllWords;
}
public void insert(Word word) {
new insertAsyncTask(mWordDao).execute(word);
}
private static class insertAsyncTask extends AsyncTask&lt;Word, Void, Void&gt; {
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, &quot;word_database&quot;)
.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&lt;Void, Void, Void&gt; {
private final WordDao mDao;
String[] words = {&quot;dolphin&quot;, &quot;crocodile&quot;, &quot;cobra&quot;};
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 &lt;= 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)&#160;
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)&#160;
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)&#160;
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)&#160;
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)&#160;
at android.os.Handler.dispatchMessage(Handler.java:106)&#160;
at android.os.Looper.loop(Looper.java:223)&#160;
at android.app.ActivityThread.main(ActivityThread.java:7656)&#160;
at java.lang.reflect.Method.invoke(Native Method)&#160;
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)&#160;
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)&#160;
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)&#160;
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)&#160;
at com.example.roomwords_sample.MainActivity.onCreate(MainActivity.java:32)&#160;
at android.app.Activity.performCreate(Activity.java:8000)&#160;
at android.app.Activity.performCreate(Activity.java:7984)&#160;
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)&#160;
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)&#160;
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)&#160;
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)&#160;
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)&#160;
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)&#160;
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)&#160;
at android.os.Handler.dispatchMessage(Handler.java:106)&#160;
at android.os.Looper.loop(Looper.java:223)&#160;
at android.app.ActivityThread.main(ActivityThread.java:7656)&#160;
at java.lang.reflect.Method.invoke(Native Method)&#160;
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)&#160;
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)&#160;
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method &#39;com.example.roomwords_sample.WordDao com.example.roomwords_sample.WordRoomDatabase.wordDao()&#39; on a null object reference
at com.example.roomwords_sample.WordRepository.&lt;init&gt;(WordRepository.java:18)
at com.example.roomwords_sample.WordViewModel.&lt;init&gt;(WordViewModel.java:18)
at java.lang.reflect.Constructor.newInstance0(Native Method)&#160;
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)&#160;
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)&#160;
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)&#160;
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)&#160;
at com.example.roomwords_sample.MainActivity.onCreate(MainActivity.java:32)&#160;
at android.app.Activity.performCreate(Activity.java:8000)&#160;
at android.app.Activity.performCreate(Activity.java:7984)&#160;
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)&#160;
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)&#160;
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)&#160;
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)&#160;
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)&#160;
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)&#160;
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)&#160;
at android.os.Handler.dispatchMessage(Handler.java:106)&#160;
at android.os.Looper.loop(Looper.java:223)&#160;
at android.app.ActivityThread.main(ActivityThread.java:7656)&#160;
at java.lang.reflect.Method.invoke(Native Method)&#160;
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)&#160;
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, &quot;word_database&quot;)
.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, &quot;word_database&quot;)
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}

huangapple
  • 本文由 发表于 2020年9月20日 04:07:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63972983.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定