Home > Blockchain >  Want to add a delay for textView when using livedata that pass LatLon
Want to add a delay for textView when using livedata that pass LatLon

Time:05-25

Are passing data between a service to a fragment using a MutableLiveData. Accordenly to a Log.d statement the data is recived. But when i try to use TextView to display the data i get null. It think a delay makes it null. Is there a way to delay or update the textview so i can display the data?

DashbordFragment.kt

class DashbordFragment : Fragment() {

private var locationList = mutableListOf<LatLng>()
var liveLatLng = MutableLiveData<LatLng>()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setHasOptionsMenu(true)
    sendActionCommandToService(Constants.ACTION_SERVICE_START)
}

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    observerTrackerService()
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_dashbord, container, false)
}
lateinit var binding : FragmentDashbordBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    binding = FragmentDashbordBinding.bind(view)

    binding.btGotostation.setOnClickListener {

        startActivity(Intent(requireContext(),StationsActivity::class.java))
    }
    binding.btGotostatistics.setOnClickListener {
        findNavController().navigate(DashbordFragmentDirections.actionDashbordFragmentToStatisticsFragment())
    }

    binding.btGotolinediagram.setOnClickListener {
        findNavController().navigate(DashbordFragmentDirections.actionDashbordFragmentToLineDiagramFragment())
    }

    binding.btMap.setOnClickListener {
        findNavController().navigate(DashbordFragmentDirections.actionDashbordFragmentToMapsFragment())
    }
    binding.latlon.text = liveLatLng.value.toString()


}

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
    inflater.inflate(R.menu.dashboard_menu, menu)
    super.onCreateOptionsMenu(menu, inflater)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {

    return super.onOptionsItemSelected(item)
}

private fun observerTrackerService(){
    TrackerService.locationList.observe(viewLifecycleOwner) {

        if (it != null) {
            locationList = it
            Log.d("LocationList",locationList.toString())
        }
    }
    TrackerService.liveLatLng.observe(viewLifecycleOwner){

        Log.d("LiveLatLng", it.toString())
    }
    Log.d("LocationList", "Tester")

}
private fun sendActionCommandToService(action: String){
    Intent(
        requireContext(),
        TrackerService::class.java
    ).apply {
        this.action = action
        requireContext().startService(this)
    }
}

fragment_dashbord.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >


    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="top|center"
        android:text="@string/dashboard"
        android:textAlignment="center"
        android:textAppearance="@style/TextAppearance.AppCompat.Large" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/go_to_station"
        android:layout_marginStart="24dp"
        android:layout_marginTop="54dp"
        android:id="@ id/bt_gotostation"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/GoogleMap"
        android:layout_marginStart="24dp"
        android:layout_marginTop="140dp"
        android:id="@ id/btMap"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/statistics_desc"
        android:layout_marginTop="240dp"
        android:textAlignment="center"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/development_bar_chart"
        android:layout_marginStart="24dp"
        android:layout_marginTop="290dp"
        android:id="@ id/bt_gotostatistics"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/development_line_diagram"
        android:layout_marginStart="24dp"
        android:layout_marginTop="360dp"
        android:id="@ id/bt_gotolinediagram"/>

    <TextView
        android:id="@ id/latlon"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="@string/statistics_desc"
        android:layout_marginTop="500dp"
        android:textAlignment="center"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium" />

</FrameLayout>

CodePudding user response:

You are setting this in onViewCreated which is called earlier than you received the data. Instead you can set an observer as follows in onViewCreated example :

liveLatLng.observe(this , Observer {
    it?.let{
        binding.latlon.text = it.toString()
    }
})

and set the value as follows

TrackerService.liveLatLng.observe(viewLifecycleOwner){
    liveLatLng.value = it // hoping this is of type LatLng
}

Note: Consider this according to android dev docs

Make sure to store LiveData objects that update the UI in ViewModel objects, as opposed to an activity or fragment, for the following reasons: To avoid bloated activities and fragments. Now these UI controllers are responsible for displaying data but not holding data state. To decouple LiveData instances from specific activity or fragment instances and allow LiveData objects to survive configuration changes.

from developer docs

CodePudding user response:

This binding.latlon.text = liveLatLng.value.toString() has nothing in common with livedata. When used correctly, your code should look like this binding.latlon = liveLatLng and no need for delay, LiveData will do it for you. To reach this all you need is to check LiveData, DataBinding and BindingAdapter.

Small hint for required binding variable

<import type="com.google.type.LatLng" />

<variable
    name="latlon"
    type="androidx.lifecycle.MutableLiveData&lt;LatLng&gt;" />
  • Related