airbnb / mavericks

Mavericks: Android on Autopilot
https://airbnb.io/mavericks/
Apache License 2.0
5.85k stars 499 forks source link

[Jetpack Compose] Strange behavior for TextField when using setState to update state #563

Closed matt400m closed 3 years ago

matt400m commented 3 years ago

I'm not sure if this is compose bug or mavericks. I decide to post here firstly.

So when I'm using setState in onTextChange soft keyboard have a strange behavior.

  1. On first field type long text
  2. Press delete button on keyboard
  3. Observe behaviour during delete

https://drive.google.com/file/d/18l-l768rR_h9BhrOsCDlLv8yGrK2g06S/view

When I'm using mutableState or MutableStateFlow, everything works.

code:

class BugActivity : FragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val fragment = FragmentContainerView(this).apply {
            id = R.id.content
        }
        setContentView(fragment)

        supportFragmentManager.commit {
            add(fragment.id, BugFragment())
        }

    }

}

class BugFragment : Fragment(), MavericksState {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return ComposeView(requireContext()).apply {
            setContent {
                val bugViewModel = mavericksViewModel<BugViewModel, BugState>()
                val text by bugViewModel.collectAsState(BugState::text)
                val works by bugViewModel.works
                val works2 by bugViewModel.works2.collectAsState()
                Column(modifier = Modifier.background(Color.Red)) {
                    TextField(
                        value = text,
                        onValueChange = { bugViewModel.onTextChange(it) },
                        modifier = Modifier.fillMaxWidth()
                    )
                    Spacer(Modifier.height(16.dp))
                    TextField(
                        value = works,
                        onValueChange = { bugViewModel.onTextChange2(it) },
                        modifier = Modifier.fillMaxWidth())
                    Spacer(Modifier.height(16.dp))
                    TextField(
                        value = works2,
                        onValueChange = { bugViewModel.onTextChange3(it) },
                        modifier = Modifier.fillMaxWidth())
                    Spacer(Modifier.height(16.dp))
                }

            }
        }
    }
}

class BugViewModel(initialState: BugState) : MavericksViewModel<BugState>(initialState) {

    val works = mutableStateOf("")
    val works2 = MutableStateFlow("")

    fun onTextChange(newText: String) = setState {
        copy(text = newText)
    }

    fun onTextChange2(newText: String) {
        works.value = newText
    }

    fun onTextChange3(newText: String) {
        works2.value = newText
    }
}

data class BugState(val text: String = "") : MavericksState`
Namnodorel commented 3 years ago

I believe this is the same issue as #455 . It's caused by Compose being unable to deal with the slight value-setting delay that Mavericks can introduce.

matt400m commented 3 years ago

I believe this is the same issue as #455 . It's caused by Compose being unable to deal with the slight value-setting delay that Mavericks can introduce.

Yep It's related. I close this issue.