0

When I try to run my app, it crashes with this logcat error. This problem is very similar to this and this post but all mentioned solutions didn't work for me.

When I searched for this error, I found out that it's usually because of the viewmodelproviders being outdated and people recommending to use the new ViewModelProvider with Factory class but even that didn't work out for me.

java.lang.RuntimeException: Cannot create an instance of class com.emirhalici.notetakingappnvvmexample.NoteViewModel

I don't see where there could be an issue, if I have a tiny syntax error somewhere or something else. It is driving me crazy as I'm a beginner and trying to learn Android Architecture Components. I was following a youtube playlist linked here and his code worked flawlessly when he ran it. Please take a look at it before flagging it as a duplicate. I'm really out of my depth here. Thanks in advance.

logcat error

    Process: com.emirhalici.notetakingappnvvmexample, PID: 17577
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.emirhalici.notetakingappnvvmexample/com.emirhalici.notetakingappnvvmexample.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.emirhalici.notetakingappnvvmexample.NoteViewModel
    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.emirhalici.notetakingappnvvmexample.NoteViewModel
    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.emirhalici.notetakingappnvvmexample.MainActivity.onCreate(MainActivity.java:26)
    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.emirhalici.notetakingappnvvmexample.MainActivity.onCreate(MainActivity.java:26) 
    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.RuntimeException: cannot find implementation for com.emirhalici.notetakingappnvvmexample.NoteDatabase. NoteDatabase_Impl does not exist
    at androidx.room.Room.getGeneratedImplementation(Room.java:97)
    at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:1358)
    at com.emirhalici.notetakingappnvvmexample.NoteDatabase.getInstance(NoteDatabase.java:25)
    at com.emirhalici.notetakingappnvvmexample.NoteRepository.<init>(NoteRepository.java:15)
    at com.emirhalici.notetakingappnvvmexample.NoteViewModel.<init>(NoteViewModel.java:19)
    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.emirhalici.notetakingappnvvmexample.MainActivity.onCreate(MainActivity.java:26) 
    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) 

MainActivity.java

public class MainActivity extends AppCompatActivity {
private NoteViewModel noteViewModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // these didn't work
    //noteViewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication())).get(NoteViewModel.class);
    //noteViewModel = new ViewModelProvider(this).get(NoteViewModel.class);
    //noteViewModel = ViewModelProviders.of(this).get(NoteViewModel.class);
    // i tried this but this don't work either
    noteViewModel = new ViewModelProvider(this,
            ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication())).get(NoteViewModel.class);
    noteViewModel.getAllNotes().observe(this, new Observer<List<Note>>() {
        @Override
        public void onChanged(List<Note> notes) {
            // update RecyclerView
            Toast.makeText(MainActivity.this, "onChanged", Toast.LENGTH_SHORT).show();
        }
    });
} }

Note.java (entity class)

@Entity(tableName = "note_table")
public class Note {

@PrimaryKey(autoGenerate = true)
private int id;

private String title;
private String description;
private int priority;

// getters
public int getId() {
    return id;
}

public String getTitle() {
    return title;
}

public String getDescription() {
    return description;
}

public int getPriority() {
    return priority;
}

// id setter
public void setId(int id) {
    this.id = id;
}

// constructor
public Note(String title, String description, int priority) {
    this.title = title;
    this.description = description;
    this.priority = priority;
}

}

NoteDao.java

@Dao
public interface NoteDao {

@Insert
void insert(Note note);

@Update
void update(Note note);

@Delete
void delete(Note note);

@Query("DELETE FROM note_table")
void deleteAll();

@Query("SELECT * FROM note_table ORDER BY priority DESC")
LiveData<List<Note>> getAllNotes();

}

NoteDatabase.java

@Database(entities = Note.class, version = 1)
public abstract class NoteDatabase extends RoomDatabase {

private static NoteDatabase instance;

public abstract NoteDao noteDao();

public static synchronized NoteDatabase getInstance(Context context) {
    if (instance == null) {
        instance = Room.databaseBuilder(context.getApplicationContext(),
                NoteDatabase.class, "note_database")
                .fallbackToDestructiveMigration()
                .addCallback(roomCallback)
                .build();
    }
    return instance;
}

private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
    @Override
    public void onCreate(@NonNull SupportSQLiteDatabase db) {
        super.onCreate(db);
        new PopulateDbAsyncTask(instance).execute();
    }
};

private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
    private NoteDao noteDao;
    private PopulateDbAsyncTask(NoteDatabase db) {
        noteDao = db.noteDao();
    }

    @Override
    protected Void doInBackground(Void... voids) {
        noteDao.insert(new Note("Title 1","Description 1", 1));
        noteDao.insert(new Note("Title 2","Description 2", 2));
        noteDao.insert(new Note("Title 3","Description 3", 3));
        noteDao.insert(new Note("Title 4","Description 4", 1));
        noteDao.insert(new Note("Title 5","Description 5", 2));
        noteDao.insert(new Note("Title 6","Description 6", 4));
        return null;
    }
}
}

NoteRepository.java

public class NoteRepository {
private NoteDao noteDao;
private LiveData<List<Note>> allNotes;

public NoteRepository(Application application) {
    NoteDatabase database = NoteDatabase.getInstance(application);
    noteDao = database.noteDao();
    allNotes = noteDao.getAllNotes();
}

public void insert(Note note) {
    new InsertNoteAsyncTask(noteDao).execute(note);
}

public void update(Note note) {
    new UpdateNoteAsyncTask(noteDao).execute(note);
}

public void delete(Note note) {
    new DeleteNoteAsyncTask(noteDao).execute(note);
}

public void deleteAll() {
    new DeleteAllNotesAsyncTask(noteDao).execute();
}

public LiveData<List<Note>> getAllNotes() {
    return allNotes;
}

private static class InsertNoteAsyncTask extends AsyncTask<Note, Void, Void> {
    private NoteDao noteDao;

    private InsertNoteAsyncTask(NoteDao noteDao) {
        this.noteDao = noteDao;
    }

    @Override
    protected Void doInBackground(Note... notes) {
        noteDao.insert(notes[0]);
        return null;
    }
}

private static class UpdateNoteAsyncTask extends AsyncTask<Note, Void, Void> {
    private NoteDao noteDao;

    private UpdateNoteAsyncTask(NoteDao noteDao) {
        this.noteDao = noteDao;
    }

    @Override
    protected Void doInBackground(Note... notes) {
        noteDao.update(notes[0]);
        return null;
    }
}

private static class DeleteNoteAsyncTask extends AsyncTask<Note, Void, Void> {
    private NoteDao noteDao;

    private DeleteNoteAsyncTask(NoteDao noteDao) {
        this.noteDao = noteDao;
    }

    @Override
    protected Void doInBackground(Note... notes) {
        noteDao.delete(notes[0]);
        return null;
    }
}

private static class DeleteAllNotesAsyncTask extends AsyncTask<Note, Void, Void> {
    private NoteDao noteDao;

    private DeleteAllNotesAsyncTask(NoteDao noteDao) {
        this.noteDao = noteDao;
    }

    @Override
    protected Void doInBackground(Note... voids) {
        noteDao.deleteAll();
        return null;
    }
}
}

NoteViewModel.java

public class NoteViewModel extends AndroidViewModel {
private NoteRepository repository;
private LiveData<List<Note>> allNotes;

public NoteViewModel(@NonNull Application application) {
    super(application);
    repository = new NoteRepository(application);
    allNotes = repository.getAllNotes();
}

public void insert(Note note) {
    repository.insert(note);
}

public void update(Note note) {
    repository.update(note);
}

public void delete(Note note) {
    repository.delete(note);
}

public void deleteAllNotes() {
    repository.deleteAll();
}

public LiveData<List<Note>> getAllNotes() {
    return allNotes;
}

}
EricSchaefer
  • 25,272
  • 21
  • 67
  • 103
Emir Halıcı
  • 21
  • 1
  • 7
  • 1
    I would recommend taking a look into how to produce a [mre] for your problem. Not only does it usually lead you to a solution by yourself but it helps us to read your question, currently 90% of the code you've posted doesn't seem relevant. – Henry Twist Apr 22 '21 at 12:27
  • Thanks, I'll look into it. As the problem occured and I couldn't find the source, I posted all codes that could be related. Even though logcat error leads to the viewmodelprovider in mainactivity, it seems the method itself is correct. I really didn't know what to do so posted all of it. Sorry for the inconvenience. – Emir Halıcı Apr 22 '21 at 12:37
  • Making a reproducible example is more for you than us. By starting a new project and testing each simple step, you should immediately find where the problem comes from. It will be a lot quicker than someone else doing it for you. – Henry Twist Apr 22 '21 at 12:50
  • I have made same project when I started with Android development and your code looks fine. try to clear cache and restart it, [here's how to do it](https://www.youtube.com/watch?v=-OXdacHtMvA&ab_channel=eXplodeApps). – Rus_o Apr 22 '21 at 12:57
  • `ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication())).get(NoteViewModel.class);` why are you doing this? This is completely wrong. – EpicPandaForce Apr 27 '21 at 00:19

1 Answers1

0

Let me start off by saying CodeInFlow is a great source to learn from I've used him lots to help build my knowledge, Codelabs are also great and frequently updated by the Android dev team. If you are starting out I would recommend learning Kotlin over java, Kotlin is the future of android and recommend language by the Android Dev Team.

This is how you get a new or existing ViewModel.

NoteViewModel viewModel = new ViewModelProvider(this).get(NoteViewModel.class);

Using a custom ViewModel Factory is not necessary for this project. You would only want to use custom ViewModel Factory if you are passing an argument into the ViewModel constructor.

Shawn
  • 1,222
  • 1
  • 18
  • 41