简体   繁体   中英

onClick with dataBinding an ViewModel doesn't work

Im working on a project and implementing the MVVM model with databinding and navigation . My button is on a fragment that opens with a drawer menu item , the thing is when i click on the button it does nothing, the debugger doesn't go into the navigate method, I really don't know what I did wrong, can someone help?

MYACCOUNT CLASS :

class MyAccountFragment : BaseFragment() {

    private val vm: MyAccountViewModel by viewModel()


    override fun getViewModel(): BaseViewModel = vm

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = FragmentMyAccountBinding.inflate(inflater, container, false)
        context ?: return binding.root
        injectFeature()

        setToolbar(binding)
        subscribeUi(binding)

        return binding.root
    }

    /**
     * set toolbar
     * **/
    private fun setToolbar(binding: FragmentMyAccountBinding) {

        binding.appBarLayout.backClickListener = (activity as MainActivity).createOnBackClickListener()
    }

    /**
     * set ui
     * **/
    private fun subscribeUi(binding: FragmentMyAccountBinding) {
        binding.viewModel = vm
    }


}

MYACCVIEWMODEL


class MyAccountViewModel constructor() : BaseViewModel() {

    fun onAddRoomClick()
    {
        navigate(MyAccountFragmentDirections.actionMyAccountFragmentToAddRoomFragment())
    }
}

and in the xml i implemented the

android:onClick="@{() -> viewModel.onAddRoomClick()}"

Im using this pattern for all my Fragments and ViewModels , and i really dont know why it doesn't do anything, the vm initializes. On the other drawermenu fragment I also have the onClick method and it navigates to the other fragment. So if anyone knows the solution that would be helpful, thank you in advance.

the answer was in the initialization of the viewModel.

the onClick method in xml is in a content_layout that is included in a fragment_layout and instead of binding.viewModel = vm I had to do binding.content_layout.viewModel = vm.

 private fun subscribeUi(binding: FragmentMyAccountBinding) {
        binding.contentMyAccount.viewModel = vm
    }

ViewModel is not supposed to handle any kind of navigation, it will just receive the event from the UI and pass it to the controller (which might be a fragment or activity) and the latter will handle the navigation...

So one way to solve your issue is to do the following:

ViewModel

   class MyAccountViewModel constructor() : BaseViewModel() {
private val _navigateToRoomFragEvent = MutableLiveData<Boolean>(false)
val navigateToRoomFragEvent:LiveData<Boolean>
    get()=_navigateToRoomFragEvent

fun onAddRoomClick()
{
    _navigateToRoomFragEvent.value=true
}
fun resetNavigation(){
    _navigateToRoomFragEvent.value=false
}

}

Controller (Activity or Fragment)

inside **onCreate() (if it is an activity)**

viewModel.navigateToRoomFragEvent.observe(this,Observer{navigate->
//boolean value
if(navigate){
navController.navigate(//action)
}
viewModel.resetNavigation() //don't forget to reset the event
})

onActivityCreated(if it is a fragment)

viewModel.navigateToRoomFragEvent.observe(viewLifeCycleOwner,Observer{navigate->
//boolean value
if(navigate){
navController.navigate(//action)
}
viewModel.resetNavigation() //don't forget to reset the event
})

Hope it helps,

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM