'How can I handle the state value on change without using Composable in Kotlin?

I have a VM and a fragment. I want to handle the change of state.value in the fragment. How can I do that. Here is the fragment:

AndroidEntryPoint
class ImportFragment : Fragment() {
    private val importVM by viewModels<ImportFragmentVM>()
    lateinit var importButton: Button
    lateinit var createButton: Button
    lateinit var tab: TabLayout
    lateinit var createItems: Group
    lateinit var importItems: Group
    lateinit var longUrl: EditText

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.import_fragment, container, false)
        
        importButton = view.findViewById(R.id.importButton)
        createButton = view.findViewById(R.id.createButton)
        tab = view.findViewById(R.id.tab)
        createItems = view.findViewById(R.id.createGroup)
        importItems = view.findViewById(R.id.importGroup)
        longUrl = view.findViewById(R.id.longurl)
        createItems.isVisible = false
        Timber.d("tab position:" + tab.selectedTabPosition)
        tab.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {

            override fun onTabSelected(tab: TabLayout.Tab) {
                when (tab.position) {
                    0 -> {
                        createItems.isVisible = false
                        importItems.isVisible = true
                        Timber.d("position 0")
                    }
                    1 -> {
                        createItems.isVisible = true
                        importItems.isVisible = false
                        Timber.d("position 1")
                    }
                }
            }

            override fun onTabUnselected(tab: TabLayout.Tab?) {
            }

            override fun onTabReselected(tab: TabLayout.Tab?) {
            }
        })
        longUrl.addTextChangedListener(object : TextWatcher {

            override fun afterTextChanged(s: Editable) {}

            override fun beforeTextChanged(
                s: CharSequence, start: Int,
                count: Int, after: Int
            ) {
            }

            override fun onTextChanged(
                s: CharSequence, start: Int,
                before: Int, count: Int
            ) {
                importVM.updateInput(longUrl.text.toString())
            }
        })

        createButton.setOnClickListener {
            val x = importVM.submit()
            if (x is ImportFragmentVM.ImportUIState.Success)
                Timber.d("assadads")
        }
        return view
    }

}

And here is the VM for this fragment:

@HiltViewModel
class ImportFragmentVM @Inject constructor(
    private val service: UrlService
) : ViewModel() {
    sealed interface ImportUIState {
        data class PendingUserInput(val longUrl: String) : ImportUIState
        object Loading : ImportUIState
        object Success : ImportUIState
        data class PartialSuccess(val urlKey: UrlKey, val urlApiKey: UrlApiKey) : ImportUIState
        object Error : ImportUIState
        object Invalid : ImportUIState

    }

    val _state = MutableStateFlow<ImportUIState>(PendingUserInput(""))
    val state: StateFlow<ImportUIState> = _state

    fun updateInput(longUrl: String) {
        check(_state.value is PendingUserInput) { "You can't be in update" }
        Timber.d("longurl:" + longUrl)
        _state.value = PendingUserInput(longUrl)
    }

    fun submit():ImportUIState {

        val longUrl = state.value.run {
            check(this is PendingUserInput) { "You can't be in update when submitting" }
            longUrl
        }
        Timber.d("sunt in submit")
        _state.value = Loading
        Timber.d("value is" + state.value)

        viewModelScope.launch(Dispatchers.IO) {
            val result = service.shortenUrl(longUrl)
            if (result is ShortenRequestOutcome.Failed)
                _state.value = Error
            if (result is ShortenRequestOutcome.Invalid)
                _state.value = Invalid
            if (result is ShortenRequestOutcome.Success)
                _state.value = Success
        }
        return state.value
    }
}

For example I want to show a dialog/toast based on the state.value, and I don't know how to find out in the fragment when the value has changed. Any ideas?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source