I'm trying to instantiate my ViewModel so that depending on which param given it will show me a different list. However, I am a bit confused about the init and constructor calls.
The below version gives me a MainViewModel> has no zero argument constructor
error.
Version 1
class MainViewModel(private val param: String) : ViewModel() {
private var list: ArrayList<ModelDialogOption>? = null
val userMutableLiveData: MutableLiveData<ArrayList<ModelDialogOption>?> = MutableLiveData()
init {
populateList()
userMutableLiveData.value = list!!
}
private fun populateList() {
list = ArrayList()
when (param) {
"Choose your age range" -> {
list!!.add(ModelDialogOption("Prefer not to say", false))
list!!.add(ModelDialogOption("16-39", false))
list!!.add(ModelDialogOption("40-59", true))
list!!.add(ModelDialogOption("60+", false))
}
}
}
}
Version 2
Whereas this gives me an empty list not finding the param since the constructor is only called after the init already took place:
class MainViewModel() : ViewModel() {
var param: String? = null
private var list: ArrayList<ModelDialogOption>? = null
val userMutableLiveData: MutableLiveData<ArrayList<ModelDialogOption>?> = MutableLiveData()
init {
populateList()
userMutableLiveData.value = list!!
}
constructor(param: String) : this() {
this.param = param
populateList()
userMutableLiveData.value = list!!
}
private fun populateList() {
list = ArrayList()
when (param) {
"Choose your age range" -> {
list!!.add(ModelDialogOption("Prefer not to say", false))
list!!.add(ModelDialogOption("16-39", false))
list!!.add(ModelDialogOption("40-59", true))
list!!.add(ModelDialogOption("60+", false))
}
}
}
}
And here another also with the empty list:
Version 3
class MainViewModel() : ViewModel() {
var param: String? = null
private var list: ArrayList<ModelDialogOption>? = null
val userMutableLiveData: MutableLiveData<ArrayList<ModelDialogOption>?> = MutableLiveData()
constructor(param: String) : this() {
this.param = param
populateList()
userMutableLiveData.value = list!!
}
private fun populateList() {
list = ArrayList()
when (param) {
"Choose your age range" -> {
list!!.add(ModelDialogOption("Prefer not to say", false))
list!!.add(ModelDialogOption("16-39", false))
list!!.add(ModelDialogOption("40-59", true))
list!!.add(ModelDialogOption("60+", false))
}
}
}
}
Version 4
And this gives me the list populate but sure without a param since not passing any but just using it as my starting point:
class MainViewModel : ViewModel() {
private var list: ArrayList<ModelDialogOption>? = null
val userMutableLiveData: MutableLiveData<ArrayList<ModelDialogOption>?> = MutableLiveData()
init {
populateList()
userMutableLiveData.value = list!!
}
private fun populateList() {
list = ArrayList()
list!!.add(ModelDialogOption("Prefer not to say", false))
list!!.add(ModelDialogOption("16-39", false))
list!!.add(ModelDialogOption("40-59", true))
list!!.add(ModelDialogOption("60+", false))
}
}
And this is my ViewModelFactory:
public class MyViewModelFactory implements ViewModelProvider.Factory {
private String param;
public MyViewModelFactory(String param) {
this.param = param;
}
@NotNull
@Override
public <T extends ViewModel> T create(@NotNull Class<T> modelClass) {
return (T) new MainViewModel(param);
}
}
Initiated this way:
private val viewModel: MainViewModel by activityViewModels {
MyViewModelFactoryForHashMap(
arguments?.getString("headerText")
)
}
Thank you very much.
Since I answered your last question I know little bit your code flow
Instead of passing param in ViewModel you should have update it because you are sharing and listening with two fragments
class CovidCheckInFragment : Fragment(R.layout.fragment_covid_check_in) {
var navController: NavController? = null
private val model: MainViewModel by activityViewModels()
private lateinit var tartTextView:TextView
@RequiresApi(Build.VERSION_CODES.M)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
tvHeader.text = "COVID Check-in"
navController = Navigation.findNavController(view)
// Listeners
etYourAge.setOnClickListener(onClick)
etYourCounty.setOnClickListener(onClick)
etYourLocality.setOnClickListener(onClick)
rbFemale.setOnClickListener(onClickRb)
rbMale.setOnClickListener(onClickRb)
rbPreferNotToSay.setOnClickListener(onClickRb)
model.userMutableLiveData.observe(viewLifecycleOwner, Observer {
it?.let {
it.filter {
it.selected == true
}.map {
tartTextView.text = it.title
}
}
})
}
private val onClick = View.OnClickListener {
val destination: Int = R.id.action_covidCheckInFragment_to_my_dialog_fragment
val message: String? = when (it.id) {
R.id.etYourAge -> {
tartTextView = etYourAge
model.updateList("Choose your age range")
"Choose your age range"
}
R.id.etYourCounty -> {
tartTextView = etYourCounty
model.updateList("Choose your county")
"Choose your county"
}
R.id.etYourLocality -> {
tartTextView = etYourLocality
model.updateList("Choose your locality")
"Choose your locality"
}
else -> {
""
}
}
val bundle = bundleOf("headerText" to message)
navController = Navigation.findNavController(it)
navController!!.navigate(
destination,
bundle
)
}
@RequiresApi(Build.VERSION_CODES.M)
private val onClickRb = View.OnClickListener {
val list = listOf<Button>(rbFemale, rbMale, rbPreferNotToSay)
for (i in list) {
i.setTextColor(resources.getColor(R.color.text))
i.background.setTint(ContextCompat.getColor(activity as MainActivity, R.color.greyEee))
}
if ((it as AppCompatRadioButton).isChecked) {
it.setTextColor(resources.getColor(R.color.white))
it.background.setTint(ContextCompat.getColor(activity as MainActivity, R.color.shadow))
}
}
}
Here is your MainViewModel
class MainViewModel : ViewModel() {
private var list = ArrayList<ModelDialogOption>()
val userMutableLiveData: MutableLiveData<ArrayList<ModelDialogOption>> = MutableLiveData()
fun updateItem(position: Int) {
val itemToUpdate = list[position]
itemToUpdate.selected = !itemToUpdate.selected!!
list[position] = itemToUpdate
}
fun flushItems() {
userMutableLiveData.value = list
}
fun updateList(param: String) {
list = ArrayList()
when (param) {
"Choose your age range" -> {
list.add(ModelDialogOption("Prefer not to say", false))
list.add(ModelDialogOption("16-39", false))
list.add(ModelDialogOption("40-59", false))
list.add(ModelDialogOption("60+", false))
}
"Choose your county" -> {
list.add(ModelDialogOption("Prefer not to say", false))
list.add(ModelDialogOption("County1", false))
list.add(ModelDialogOption("County2", false))
list.add(ModelDialogOption("County3", false))
}
"Choose your locality" -> {
list.add(ModelDialogOption("Prefer not to say", false))
list.add(ModelDialogOption("Locality1", false))
list.add(ModelDialogOption("Locality2", false))
list.add(ModelDialogOption("Locality3", false))
}
}
flushItems()
}
}