Well I am a beginner with android and kotlin so I have been trying to send a variable semesterSelected from the fragment ViewCourses to my viewmodel UserViewModel is the codes are down below.
`class ViewCourses(path: String) : ReplaceFragment() {
private var semesterSelected= path
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
container?.removeAllViews()
return inflater.inflate(R.layout.fragment_view_courses, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
userRecyclerView = view.findViewById(R.id.recyclerView)
userRecyclerView.layoutManager = LinearLayoutManager(context)
userRecyclerView.setHasFixedSize(true)
adapter = MyAdapter()
userRecyclerView.adapter = adapter
makeToast(semesterSelected)
// The variable I am trying to send to UserViewModel is -->> semesterSelected
var viewModel: UserViewModel = ViewModelProvider(this)[UserViewModel::class.java]
viewModel.allUsers.observe(viewLifecycleOwner) {
adapter.updateUserList(it)
}
}
}
class UserViewModel : ViewModel() {
private val repository: UserRepository = UserRepository("CSE/year3semester1").getInstance()
private val _allUsers = MutableLiveData<List<CourseData>>()
val allUsers: LiveData<List<CourseData>> = _allUsers
init {
repository.loadUsers(_allUsers)
}
}
The reason I am doing this is I am wanting a to send a variable to my repository UserRepository all the way from ViewCourses and thought sending this via UserViewModel might be a way .
class UserRepository(semesterSelected: String) {
// The variable I am expecting to get from UserViewModel
private var semesterSelected = semesterSelected
private val databaseReference: DatabaseReference =
FirebaseDatabase.getInstance().getReference("course-list/$semesterSelected")
@Volatile
private var INSTANCE: UserRepository? = null
fun getInstance(): UserRepository {
return INSTANCE ?: synchronized(this) {
val instance = UserRepository(semesterSelected)
INSTANCE = instance
instance
}
}
fun loadUsers(userList: MutableLiveData<List<CourseData>>) {
databaseReference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
try {
val courseList: List<CourseData> = snapshot.children.map { dataSnapshot ->
dataSnapshot.getValue(CourseData::class.java)!!
}
userList.postValue(courseList)
} catch (e: Exception) {
}
}
override fun onCancelled(error: DatabaseError) {
}
})
}
}
I tried something like below
class ViewCourses(path: String) : ReplaceFragment() {
private var semesterSelected= path
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
container?.removeAllViews()
return inflater.inflate(R.layout.fragment_view_courses, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
userRecyclerView = view.findViewById(R.id.recyclerView)
userRecyclerView.layoutManager = LinearLayoutManager(context)
userRecyclerView.setHasFixedSize(true)
adapter = MyAdapter()
userRecyclerView.adapter = adapter
makeToast(semesterSelected)
**// Sending the variable as parameter**
var viewModel: UserViewModel = ViewModelProvider(this)[UserViewModel(semesterSelected)::class.java]
viewModel.allUsers.observe(viewLifecycleOwner) {
adapter.updateUserList(it)
}
}
}
class UserViewModel(semesterSelected: String) : ViewModel() {
private val repository: UserRepository = UserRepository("CSE/year3semester1").getInstance()
private val _allUsers = MutableLiveData<List<CourseData>>()
val allUsers: LiveData<List<CourseData>> = _allUsers
init {
repository.loadUsers(_allUsers)
}
}
but doing this my app crashes . how can this be done ? Thanks in Advance.
var viewModel: UserViewModel = ViewModelProvider(this)[UserViewModel(semesterSelected)::class.java]
UserViewModel(semesterSelected)::class.java
NOR UserViewModel::class.java
is a constructor for the view model.
If you would want to have ViewModel
with that NEEDS initial parameters, you will have to create your own factory for that - which is a tad more complicated and for your case, it might be overkill for what you are trying to do but in the longterm it will pay off(Getting started with VM factories).
With that said, your needs can be easily solved by one function to initialize the view model.
class UserViewModel() : ViewModel() {
private lateinit var repository: UserRepository
private val _allUsers = MutableLiveData<List<CourseData>>()
val allUsers: LiveData<List<CourseData>> = _allUsers
fun initialize(semesterSelected: String) {
repository = UserRepository("CSE/year3semester1").getInstance()
repository.loadUsers(_allUsers)
}
}