Androidew1267
Androidew1267

Reputation: 613

Can't get access to Views by DataBinding or Android Extensions

I can't change value of Views by DataBinding or by Android Extensions, but it works by 'traditional way' (findViewById). Also, it throws NPE when I try by Android Extensions' way without safe call operator.

HourlyFragment.kt

class HourlyFragment : Fragment() {

private lateinit var binding: FragmentHourlyBinding

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

    var rootView = inflater.inflate(R.layout.fragment_hourly, container, false)

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

    // doesn't work
    //binding.tvHourly.text = "HOURLY!"

    val tvHourly : TextView = rootView.findViewById(R.id.tv_hourly)
    tvHourly.setText("HOURLY!!")

    // doesn't work, without safe call operator throws NullPointerException
    //tv_hourly?.text = "HOURLY!!!"

    return rootView
}

}

fragment_hourly.xml

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

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".fragments.HourlyFragment">


        <TextView
            android:id="@+id/tv_hourly"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="hourly fragment" />

    </FrameLayout>
</layout>

Upvotes: 3

Views: 1273

Answers (3)

Hossein Mirzazadeh
Hossein Mirzazadeh

Reputation: 16

In a more concise and more readable way:


private lateinit var binding: FragmentHourlyBinding

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

    binding = FragmentHourlyBinding.inflate(
        inflater, container, false
    ).apply {
        tvHourly.text = "HOURLY!"
    }

    return binding.root
}

Upvotes: 0

Tenfour04
Tenfour04

Reputation: 93609

Why your data binding doesn't work:

You are manually inflating with the line

var rootView = inflater.inflate(R.layout.fragment_hourly, container, false)

but then you use data binding to inflate another copy of this hierarchy in the next line of code. You then return the first layout from onCreateView, throwing away your second inflated data binding layout. You changed the text of the view in the data binding layout that you then threw away.

Why your Android Extensions doesn't work:

You can't use the synthetic view references before onCreateView() returns, because the Fragment still doesn't have any view attached to it for the synthetic property to use to find the child view.

You should be modifying view content in onViewCreated() instead.

By the way, Android Extensions is deprecated and should no longer be used.

Upvotes: 2

Dhanuesh
Dhanuesh

Reputation: 1596

Currently you are inflating your views twice and that's causing all the issues I believe, so instead just inflate your views once and see if it solves your issue

Try the following

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

 // var rootView = inflater.inflate(R.layout.fragment_hourly, container, false)

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

    binding.tvHourly.text = "HOURLY!"

   // val tvHourly : TextView = rootView.findViewById(R.id.tv_hourly)
    tvHourly.setText("HOURLY!!")

   

    return binding.root
}

Upvotes: 3

Related Questions