Search code examples
androidandroid-fragmentsmvvmandroid-livedataandroid-databinding

Android MVVM Databinding EditText value lost onConfigurationChanged in Fragment


I am having an issue using Databinding in a Fragment.

Short problem: Value entered in my EditText is lost when I change my phone orientation.

Details: First my fragment is created through navigation component. So my activity looks like this:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        navController = findNavController(R.id.my_nav_host_fragment)
    }
}

So I arrive in a first fragment (a list) with edit button on every element of the list. Then you click on "edit" and you arrive into the second fragment. The issue is here. This is a simple form with one EditText and some other information.

I am trying Two-Way Databinding like this:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="myViewModel"
            type="my.package.name.MyViewModel" />

    </data>
[...]

    <EditText 
        [...]
        android:text="@={myViewModel.name}"
        [...] />
[...]

In my ViewModel:

class MyViewModel @Inject constructor(
    private val repo: MyRepository
) : ViewModel() {
    val name = MutableLiveData<String?>()
    //rest of the ViewModel

Finally in my Fragment:

@AndroidEntryPoint
class MyFragment : Fragment() {

    private lateinit var binding: MyFragmentBinding
    private var myObject: myObject? = null

    @Inject
    lateinit var myViewModel: MyViewModel

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        val safeArgs: MyFragmentArgs by navArgs()
        myObject = safeArgs.myObject

        binding = DataBindingUtil.inflate(
            inflater,
            R.layout.my_fragment,
            container,
            false
        )

        binding.lifecycleOwner = this
        binding.myViewModel = myViewModel

        return binding.root
    }

In my fragment I have a button to save and if I enter "example" in my EditText then click the button the value is ok in my ViewModel, I get "example".

But my issue is: If I enter "example" then turn my phone in landscape the value in EditText is lost.

I tried to debug and found out that when I rotate my phone I go to the "onCreateView" of my Fragment again. So my guess is that I recreate a new ViewModel...

Any help would be appreciated! Thanks in advance!


Solution

  • Should be

    @HiltViewModel
    class MyViewModel @Inject constructor(
        private val repo: MyRepository
    ) : ViewModel() {
    

    And

    private val myViewModel by viewModels<MyViewModel>()