Abhishek
Abhishek

Reputation: 49

How to send values from fragment to viewmodel (Repository)?

I am working on an MVVM architecture-based app where I have a value that users select on the fragment which I have to update in the API call request that I am making in the RepositoryImpl class using LiveData, how could I do this?

class Fragment1 : ScopedFragment(), KodeinAware {
    override val kodein by closestKodein()
    private val viewModelFactory: Fragment1ViewModelFactory by instance()

    private lateinit var viewModel: Fragment1ViewModel

    private var selected1 = ""
    private var selected2 = ""
    private var selected3 = ""

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment1, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProvider(this, viewModelFactory)
            .get(Fragment1ViewModel::class.java)
        bindUI()
        }

        setSpinner1()
        setSpinner2()

        setButton.setOnClickListener {
            val modalbottomSheetFragment = MyBottomSheetDialogFragment()
            modalbottomSheetFragment.show(parentFragmentManager, modalbottomSheetFragment.tag)
        }

    }

    private fun bindUI() = launch {
        valueContainer.visibility = View.VISIBLE
        val currentValue = viewModel.fragment1
        currentValue.observe(viewLifecycleOwner, Observer {
            if (it == null) return@Observer
            value.text = it.Val
        })
        comboSelected = selected1 + selected2
    }

comboSelected is the value that I have to pass to the repository so that I could fetch the value of the selected value pair.

Repository Code -

class NameRepositoryImpl(
    private val NameValueDao: NameValueDao,
    private val NameNetworkDataSource: NameNetworkDataSource
) : NameRepository {

    init {
        NameNetworkDataSource.downloadedName.observeForever { newNameValue ->
            persistFetchedNameValue(newNameValue)
        }
    }

    private val value: Flow<NameResponseDB> = NameValueDao.getNameValue()

    override suspend fun getCurrentValue() {
        return withContext(Dispatchers.IO) {
            initNameData()
        }
    }

    override fun getCurrentNameValue(): Flow<NameResponseDB> {
        return value
    }

    private fun persistFetchedNameValue(nameValue: NameResponse) {
        GlobalScope.launch(Dispatchers.IO) {
            NameValueDao.upsert(
                NameResponseDB(
                    valueCode = NameValue.valueCode,
                    nameVal = NameValue.nameVal
                )
            )
        }
    }

    private suspend fun initNameData() {
        if (isFetchNameNeeded(ZonedDateTime.now().minusMinutes(30)))
            fetchNameValue()
    }

    private suspend fun fetchNameValue() {
        NameNetworkDataSource.fetchCurrentValue(valueCode = "**Need the combo Selected Value here**")
        val value = NameNetworkDataSource.fetchCurrentValue(valueCode = "**Need the combo Selected Value here**")
    }
}

Upvotes: 0

Views: 573

Answers (1)

mehul bisht
mehul bisht

Reputation: 742

I haven't used Kodein specifically but I have used Dependency Injection with MVVM using Koin and also Dagger Hilt, so the basic idea should still remain the same here as well.

You need to provide an instance of your repository to the viewModel, and remove private from that function fetchNameValue so that viewModel can call this suspend fun via the viewmodelscope. Also, viewModel and repository are not the same thing. You should create their logic separately. So it should be like this:

Fragment

private fun bindUI() = launch {
    valueContainer.visibility = View.VISIBLE
    val currentValue = viewModel.fragment1
    currentValue.observe(viewLifecycleOwner, Observer {
        if (it == null) return@Observer
        value.text = it.Val
    })
    comboSelected = selected1 + selected2
    viewModel.doSomething(comboSelected)
}

ViewModel

class MyVm(
 private val repository: Repository          // inject respository
): ViewModel() {

    fun doSomething(value: String) {

         viewModelScope.launch {
         repository.fetchNameValue(value)
         }
    }
}

Repository

class Repository {

    suspend fun fetchNameValue(nameValue: String) {
    NameNetworkDataSource.fetchCurrentValue(valueCode = nameValue)
    val value = NameNetworkDataSource.fetchCurrentValue(valueCode = nameValue)
}
}

If you still have a doubt, let me know, I'll try to update my answer :)

Upvotes: 1

Related Questions