blonsky95 / TimeStopperAndroid

0 stars 0 forks source link

Data binding #47

Closed blonsky95 closed 3 years ago

blonsky95 commented 3 years ago

First for data binding:

  1. use it for speed number to be updated directly through that - fragment is already doing that - not through viewmodel

  2. visibility of player_controls which is the play, forward, rewind next, previous frame buttons - not really good idea, it works together with the fragments and the livedata just sends a tap notification, not the actual visibility state that should be applied

  3. can i use it for the timing info layout as well? so the text --> Yes the text is being updated through data binding with livedata

  4. Try binding ActionButtonsFragment to its xml, it doesnt need a viewmodel, it isnt observing livedata, so just bind them together and then use the interface variable - DONE

  5. Try with speed interface if something can be done with databinding - DONE

blonsky95 commented 3 years ago

Ok so basic rules are:

add to build.gradle in app:

buildFeatures {
    dataBinding true
}

In the xml add a couple things:

       <layout xmlns:android="http://schemas.android.com/apk/res/android"
           xmlns:app="http://schemas.android.com/apk/res-auto"
           xmlns:tools="http://schemas.android.com/tools">

to wrap all the layout code, so you can put under this component the data annotation/component just like this:

<data>
    <variable
        name="mainViewModel"
        type="com.tatoeapps.tracktimer.viewmodel.MainViewModel" />
</data>

where name is the variable you are going to use in the binding activity, and type its type

In the activity:

        val binding: com.tatoeapps.tracktimer.databinding.ActivityMainBinding =
            DataBindingUtil.setContentView(this, layout.activity_main)
        binding.mainViewModel = mainViewModel
        binding.lifecycleOwner = this

where ActivityMainBinding is a self generated class by enabling binding and adding the code to the xml. It generates the name by doing "layout file name" -> to Pascal + Binding _e.g. mainactivity would be MainActivityBinding And DataBindingUtil is a binding normal class that has to be imported If a fragment, the lifecycleOwner should be getLifecycleOwner

In this example the text of a textview has the following value

            android:text="@{mainViewModel.timingDisplayText}"

which is a livedata field, and is working well

blonsky95 commented 3 years ago

So, to add a method in onClick, as usually you are not interested in the view parameter that comes with it, you can do this:

        android:onClick="@{() -> actionButtonsInterface.importVideo()}"
blonsky95 commented 3 years ago

And to implement databinding in a fragment there is a slight difference:

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

    val binding = FragmentActionBtnsBinding.inflate(inflater, container, false)
    fragmentActionBtnsBinding = binding
    binding.actionButtonsInterface=mActionButtonsInterface

    return binding.root
}

and

override fun onDestroyView() {
    fragmentActionBtnsBinding=null
    super.onDestroyView()
}

First the binding variable is created through inflate Then to account for the lifecycle awareness there is a variable (fragmentActionBtnsBinding) which is initialised to null, and when view is destroyed is set to null again, aka, when no fragment, no binding. Then the variable in xml (the field in ) is assigned with "binding.variablename=variable in fragment" and finally its the binding.root that returns the view for the fragment

blonsky95 commented 3 years ago

For Livedata binding, I initialise the data as livedata, and then I postvalue to it like normally, but this livedata isnt observed anywhere. But remember to also add:

    binding.lifecycleOwner=viewLifecycleOwner

or "this" if it is an activity (the example is from a fragment)

from https://proandroiddev.com/advanced-data-binding-binding-to-livedata-one-and-two-way-binding-dae1cd68530f

Starting using LiveData with Data Binding To use a LiveData object with your binding class, you need to specify a lifecycle owner to define the scope of the LiveData object.