'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 |
|---|
