0

I am getting this error from a while and i have tried everything to resolve this error I have seen this solution but it didn't work for me: Cannot create an instance of ViewModel Class

  1. I have tried using the ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())
  2. I have also tried by making my own custom viewModelFactory still i am unable to resolve the error
  3. I have tried making this project in kotlin also and in kotlin it is working fine. But i also want to make it in java.

Error is:-

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.aashushaikh.notesjava, PID: 22110
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.aashushaikh.notesjava/com.aashushaikh.notesjava.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.aashushaikh.notesjava.viewModel.NoteViewModel
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
     Caused by: java.lang.RuntimeException: Cannot create an instance of class com.aashushaikh.notesjava.viewModel.NoteViewModel
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:269)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
        at com.aashushaikh.notesjava.MainActivity.onCreate(MainActivity.java:42)
        at android.app.Activity.performCreate(Activity.java:6679)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6119) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
     Caused by: java.lang.NoSuchMethodException: <init> [class android.app.Application]
        at java.lang.Class.getConstructor0(Class.java:2204)
        at java.lang.Class.getConstructor(Class.java:1683)
        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.aashushaikh.notesjava.MainActivity.onCreate(MainActivity.java:42) 
        at android.app.Activity.performCreate(Activity.java:6679) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6119) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 

MainActivity.java

public class MainActivity extends AppCompatActivity implements NoteClicked{

    RecyclerView recyclerView;
    Button btnSubmit;
    EditText input;
    NoteRVAdapter noteRVAdapter;
    NoteViewModel viewModel;

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

        recyclerView = findViewById(R.id.recyclerView);
        btnSubmit = findViewById(R.id.addButton);
        input = findViewById(R.id.input);

//        viewModel = ViewModelProviders.of(this, new MyViewModelFactory(this.getApplication(), "My factory")).get(NoteViewModel.class);
        viewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(NoteViewModel.class);

        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        noteRVAdapter = new NoteRVAdapter(this, this);
        recyclerView.setAdapter(noteRVAdapter);

        viewModel.allNotes.observe(this, new Observer<List<Note>>() {
            @Override
            public void onChanged(List<Note> notes) {
                if(notes != null){
                    noteRVAdapter.updateList(notes);
                }
            }
        });

        btnSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String noteText = input.getText().toString();
                if(!noteText.isEmpty()){
                    viewModel.insertNote(new Note(noteText));
                    Toast.makeText(MainActivity.this, "Note inserted", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    @Override
    public void noteClicked(Note note) {
        viewModel.deleteNote(note);
    }


}

NoteViewModel.java

public class NoteViewModel extends AndroidViewModel {

    private NoteRepository noteRepository;
    public LiveData<List<Note>> allNotes;

    public NoteViewModel(@NonNull @NotNull Application application, String mParam) {
        super(application);

        NoteDao dao = NoteDatabase.getInstance(application).getNoteDao();
        noteRepository = new NoteRepository(dao);
        allNotes = noteRepository.getAllNotes();
    }

    public void deleteNote(Note note){
        noteRepository.delete(note);
    }
    public void insertNote(Note note){
        noteRepository.insert(note);
    }
    public LiveData<List<Note>> getAllNotes(){
        return allNotes;
    }
}

NoteRepository.java

public class NoteRepository {
    NoteDao noteDao;
    public LiveData<List<Note>> allNotes = noteDao.getAllNotes();
    public NoteRepository(NoteDao noteDao) {
        this.noteDao = noteDao;
    }

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

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

    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 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;
        }
    }

}

NoteDatabase.java

@Database(entities = {Note.class}, version = 1, exportSchema = false)
public abstract class NoteDatabase extends RoomDatabase {
    public abstract NoteDao getNoteDao();
    private static NoteDatabase instance;

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

}

NoteDao.java

@Dao
public interface NoteDao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    void insert(Note note);

    @Delete
    void delete(Note note);

    @Query("SELECT * FROM note_table ORDER BY id ASC")
    LiveData<List<Note>> getAllNotes();
}

Note.java

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

    @PrimaryKey(autoGenerate = true)
    public int id;

    @ColumnInfo(name = "text")
    public String text;

    public Note(String text) {
        this.text = text;
    }
}
Aashu Shaikh
  • 21
  • 1
  • 1
  • 3
  • it's obviously because your view model has unexpected parameter in constructor ... just remove `String mParam` and everything would be works fine ... or read documentation how to provide custom parameter to view model constructor – Selvin Jun 20 '22 at 11:03
  • you need to provide a Custom Factory for the extra param. check my answer below. – AagitoEx Jun 20 '22 at 11:38

1 Answers1

0

if this is your Factory class

public class MyFactory implements ViewModelProvider.Factory {
    private Application mApplication;
    private String mParam;


    public MyFactory(Application application, String param) {
        mApplication = application;
        mParam = param;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> aClass) {
        return (T) new NoteViewModel(mApplication, mParam);
    }
}

Try this

viewModel = new ViewModelProvider(this, new MyFactory(getApplication(), "viewModel")).get(NoteViewModel.class);
AagitoEx
  • 484
  • 2
  • 8
  • after doing this it is giving "java.lang.NullPointerException: Attempt to invoke interface method 'androidx.lifecycle.LiveData com.aashushaikh.notesjava.room.NoteDao.getAllNotes()' on a null object reference" this error, idk how am i getting this NodeDao object as a null object And also i want to ask that can i make this view model object by using the AndroidViewModelFactory provided by android?? – Aashu Shaikh Jul 02 '22 at 15:21