'How to use Intent and ViewModelFactory in a fragment
I was following a tutorial by geekbygeeks they made a todo list in an activity but I want to put mine in a fragment.
So As a beginner I ran into a bunch of errors.
The first one is initializing the adapter class (of a recyclerviwer) in the Fragment.kt class
// on below line we are initializing our adapter class.
val noteRVAdapter = NoteRVAdapter(this, this, this)
I think because this refers to activities and not fragment, I get errors for the parameter this.
although if I change the first parament this to this.context it stops the error of the first parameter. (i.e)
val noteRVAdapter = NoteRVAdapter(this.context, this, this)
but I don't really know the meaning of this nor if it will work when I run the App.
Here is the NoteRVAdapter.kt file (which was initialize in the fragment.kt) :
class NoteRVAdapter(
val context: Context,
val noteClickDeleteInterface: NoteClickDeleteInterface,
val noteClickInterface: NoteClickInterface
) :
RecyclerView.Adapter<NoteRVAdapter.ViewHolder>() {
// on below line we are creating a
// variable for our all notes list.
private val allNotes = ArrayList<Note>()
....
The next Error I encountered was an Unresolved reference: application from ViewModel,
ViewModelProvider.AndroidViewModelFactory.getInstance(application)
).get(...
The application parameter of getInstance gives an Unresolved reference error even though it requires the parameter.
Here's more code of the ViewModel in the fragment.kt
// on below line we are
// initializing our view modal.
viewModal = ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory.getInstance(application)
).get(NoteViewModal::class.java)
This next error is on intent.
I got an unresolved reference error on @MainActivty and finish, in the code below
val intent = Intent(this@MainActivity, AddEditNoteActivity::class.java)
startActivity(intent)
this.finish()
I am not familiar with the intent but I think the this@MainActivity shouldn't be there, as I want to put this in a fragement (DashboardFragment) not an activity.
here's the whole code, the the fragment.kt file:
binding.idFAB.setOnClickListener {
// adding a click listener for fab button
// and opening a new intent to add a new note.
val intent = Intent(this@MainActivity, AddEditNoteActivity::class.java)
startActivity(intent)
this.finish()
}
And finally I got a similar error on intent here; (also in the fragment.kt file)
override fun onNoteClick(note: Note) {
// opening a new intent and passing a data to it.
val intent = Intent(this@MainActivity, AddEditNoteActivity::class.java)
intent.putExtra("noteType", "Edit")
intent.putExtra("noteTitle", note.noteTitle)
intent.putExtra("noteDescription", note.noteDescription)
intent.putExtra("noteId", note.id)
startActivity(intent)
this.finish()
}
The difference is that the finish() declared last, gives an unresolved referenceerror, and the override at the start gives an error, saying onNoteClick' overrides nothing
please by fragment.kt I mean the fragment (DashboardFragment) I want to put the todo list.
I know this is a lot, but any feedback will be greatly appreciated.. And I am more than happy to provide any other information if required.
Thanks massively for your help in advance, I honestly appreciate,
Solution 1:[1]
TLDR: Replace this and this@MainActivity with requireContext(). Add requireContext(). in front of startActivity() and add requireActivity(). in front of finish().
What is Context? is kind of meme among Android developers because it is so hard to explain. It's basically something you need an instance of to use many different Android classes. The weird thing is, an Activity is a Context (it's a subclass of it), but a Fragment gets attached to a Context. So when you are passing a Context parameter to a class constructor, an Activity can pass itself as this, but a Fragment has to get a reference to its attached context and pass that.
In a Fragment you can replace this with requireContext(). You usually need requireContext() instead of just context because context is nullable. They made it nullable because it is null during certain stages of the Fragment lifecycle. You need to remember not to use requireContext() in property initializers or callbacks (other than UI listeners) because property initializers are called before there is an attached context and callbacks could get fired when there is no context available and cause a crash.
When you see this@MainActivity instead of this, that's because that class named MainActivity wants to pass itself as the context, but it's doing it inside a listener interface. In that context, this would be the listener, not the Activity, so the code has to clarify which this it is referring to, which is done with @ and the name of the outer class.
Once again, since you're in a Fragment, you should pass requireContext() for that parameter instead. Since it's in a click listener, which can only be called while the Fragment is attached, it's safe to use requireContext().
startActivity() is a function of Context. That's why in an Activity, you can simply call it from anywhere. In a Fragment, you need to use requireContext().startActivity().
finish() is specifically a function of an Activity so you can't call it on a Fragment. If you want to finish the Activity that contains the Fragment, you can call requireActivity().finish(). But since you're replacing your Activity with a Fragment, your structure of how you're organizing the screens of your app is different, so this may not be a one-to-one correspondence with what the original code was doing.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Tenfour04 |
