I have:
I have a button in fragment_main.xml. I can easily pass it android:onClick="navigate" and have the function navigate() in MainActivity create an intent and start SecondActivity like so:
fun navigate(v: View) {
intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
But what if I want the button to navigate to a different activity (ThirdActivity) if a bool is true?
This is what I've tried, but the binding in the MainActivity doesn't work:
class MainViewModel : ViewModel() {
val navBoolLiveData = MutableLiveData<Boolean>()
fun navigate() {
val boolio = false
navBoolLiveData.postValue(boolio)
}
}
class MainActivity : AppCompatActivity(R.layout.activity_main) {
private val viewModel: MainViewModel by viewModels()
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
if (savedInstanceState == null) {
supportFragmentManager.commit {
setReorderingAllowed(true)
add<MainFragment>(R.id.fragment_container_view)
}
}
}
private fun navigateObserver() {
// this is never called
viewModel.navBoolLiveData.observe(this) { boolio ->
if (!boolio) {
intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
} else {
intent = Intent(this, ThirdActivity::class.java)
startActivity(intent)
}
}
}
}
I have a feeling I'm going about this all wrong. My binding in MainFragment does work, but I wasn't sure it should even be involved in the navigation logic or actual nav call.
What is the right way to do this?
You are missing call to navigateObserver()
in your onCreate()
. Also, to use LiveData for events such as navigation, you should reset the state after the change is consumed. i.e. after you are done navigating. This is help in preventing bugs. Below is an example:
val navigationEvent = MutableLiveData<Boolean>()
fun navigationEventComplete() {
navigationEvent.value = false
}
viewModel.navigationEvent.observe(viewLifecycleOwner, Observer {
if (it == true) {
navigate()
// after navigation reset the state, to signal you are done navigating
viewModel.navigationEventComplete()
}
})