Lỗi view inflater.inflate r.layout.fragment_map container false năm 2024

ViewBinding is a part of Android Jetpack. View binding is a feature that allows you to more easily write code that interacts with views. It replaces the use of findViewById and kotlin synthetics. The View reference it returns is both Type-Safe and Null Safe. Using FindViewById is not null safe as well as not type-safe

So before explaining ViewBinding I will explain Type Safety and Null Safety with examples.

Type Safety

Let’s suppose we are using FindViewById for getting references of views. I will explain this by taking a suitable example.

In the below code I am simply using findViewById for getting the TextView reference this will compile without errors.

class MainActivity : AppCompatActivity[] {

private lateinit var tv1:TextView  
override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    setContentView[R.layout._activitymain_]  
    tv1 = findViewById[R.id._tvoutput1_]  
    tv1._text_ = "Hello World"  
}
You can see the output Hello World.

Now If I just change the type of tv1 to Button it will compile but gives an exception this is the problem with FindViewById it is not Type-Safe. meaning of type safety is that the compiler will validate types while compiling, and throw an error if you try to assign the wrong type to a variable. but in this case, it does clear compilation but throws exception.

class MainActivity : AppCompatActivity[] {

private lateinit var tv1:Button  
override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    setContentView[R.layout._activitymain_]  
    tv1 = findViewById[R.id._tvoutput1_]  
    tv1._text_ = "Hello World"  
}  
}

Caused by: java.lang.ClassCastException: com.google.android.material.textview.MaterialTextView cannot be cast to android.widget.Button at com.example.myapplication.MainActivity.onCreate[MainActivity.kt:15] at android.app.Activity.performCreate[Activity.java:7994] at android.app.Activity.performCreate[Activity.java:7978] at android.app.Instrumentation.callActivityOnCreate[Instrumentation.java:1309] at android.app.ActivityThread.performLaunchActivity[ActivityThread.java:3422]

Null Safety

Problem with FindViewById

Now Let’s take the example of the same mainActivity and use the same tv1 variable of type TextView but this time I will create another layout file and add a TextView in that. Now I will use the id of that Text View.

class MainActivity : AppCompatActivity[] {

private lateinit var tv1:TextView  
override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    setContentView[R.layout._activitymain_]  
    tv1 = findViewById[R.id.**_tvincludeoutput1_**]  
    tv1._text_ = "Hello World"  
}  
}

This is the XML of another layout.


This will produce this Exception

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.NullPointerException: findViewById[R.id.tv_include_output1] must not be null

Here this is generated because we are trying to access a view of another layout which is why using FindViewById is not null safe.

Problem with Kotlin Synthetics

Now I will explain the problem with Kotlin Synthetics. for that you need to enable it. just add this ‘kotlin-android-extensions’ in build.gradle[:app] file under plugins.

Now you are good to go

So I will take the same example for explaining it. So now we can directly access view by using their ids only. It will produce the same output as above

tv_output1.text ="Hello World"

Here the view is Type-Safe but not Null-Safe. I can access the TextView present in another layout. it will produce the same NullPointer Exception.

Here I am using the text view which is not associated with activity_main.xml

class MainActivity : AppCompatActivity[] {

override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    setContentView[R.layout._activitymain_]  
    tv_include_output1._text_ ="Hello World"  
}  
}

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.widget.TextView.setText[java.lang.CharSequence]’ on a null object reference

Now I will explain ViewBinding from basics.

View Binding

I will explain how to use view binding in different cases like Activity, Fragment, Custom Views, etc.

Before this, you have to enable view binding go to build.gradle[:app] and add this

buildFeatures*{*

viewBinding  true  
}

Now You can use ViewBinding without any hindrance

First I will start with Activity

Activity

This is how you can use ViewBinding in an Activity. before setContextView just define a variable binding which is of the type ActivityMainBinding.there are many inflate methods for an activity you have to use this inflate method because we don't have any parent view object to pass.

using binding.root you will get the layout root view

class MainActivity : AppCompatActivity[] {

override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    val binding = ActivityMainBinding.inflate[_layoutInflater_]  
    setContentView[binding._root_]  
    binding.tvOutput1._text_="Hello"  
    binding.tvOutput2._text_="View Binding"  
    binding.btnClickMe.setOnClickListener **{** 
        Toast.makeText[_applicationContext_,"Hello TO View Binding",Toast._LENGTHLONG_].show[]  
    **}** 
}  
}

Output :

Fragment

Now create a BlankFragment.Just follow the below picture

Now in the onCreateView, you can use binding but here the inflate method will change because we have a parent view.

class BlankFragment : Fragment[] {

lateinit var binding: FragmentBlankBinding
override fun onCreateView[inflater: LayoutInflater, container: ViewGroup?,  
                          savedInstanceState: Bundle?]: View {  
    _// Inflate the layout for this fragment_ 
    binding = FragmentBlankBinding.inflate[inflater,container,false]  
    binding.fragementTextView._text_ = "I am in Fragment"  
    return binding._root_ 
}
companion object {  
    @JvmStatic fun newInstance[] =  
            BlankFragment[]  
}  
}

Code to attach Blank Fragment to MainActivity

class MainActivity : AppCompatActivity[] {

override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    val binding = ActivityMainBinding.inflate[_layoutInflater_]  
    setContentView[binding._root_]  
    binding.tvOutput1._text_="Hello"  
    binding.tvOutput2._text_="View Binding"  
    binding.btnClickMe.setOnClickListener **{** 
    Toast.makeText[_applicationContext_,"Hello TO View   Binding",Toast._LENGTHLONG_].show[]  
    **}** 
    _supportFragmentManager_.beginTransaction[]  
      .add[R.id._containerfragment_,BlankFragment.newInstance[]]  
      .commit[]  
}  
}

Custom Views

You can create a custom view just go to UIComponent in the options. Here we are creating a variable binding and initializing it. here we just pass this as parent view group and init block you can initialize your views.

class MainActivity : AppCompatActivity[] {

private lateinit var tv1:Button  
override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    setContentView[R.layout._activitymain_]  
    tv1 = findViewById[R.id._tvoutput1_]  
    tv1._text_ = "Hello World"  
}  
}

0

Include Tag

for include tags you just have to mention the id in the layout tag and can get the binding of that included layout by just calling

class MainActivity : AppCompatActivity[] {

private lateinit var tv1:Button  
override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    setContentView[R.layout._activitymain_]  
    tv1 = findViewById[R.id._tvoutput1_]  
    tv1._text_ = "Hello World"  
}  
}

1

Merge Tag

For Merge tags, you can’t use ids to get the view. you have to call in onCreate of activity or in onCreateView of fragment

class MainActivity : AppCompatActivity[] {

private lateinit var tv1:Button  
override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    setContentView[R.layout._activitymain_]  
    tv1 = findViewById[R.id._tvoutput1_]  
    tv1._text_ = "Hello World"  
}  
}

2

Now I will talk about something which you should not do while using view binding

  1. Never Add the Custom View as the root and in the custom view don’t use Viewbinding at the same time.

what I want to say is this don’t do both at the same time.

class MainActivity : AppCompatActivity[] {

private lateinit var tv1:Button  
override fun onCreate[savedInstanceState: Bundle?] {  
    super.onCreate[savedInstanceState]  
    setContentView[R.layout._activitymain_]  
    tv1 = findViewById[R.id._tvoutput1_]  
    tv1._text_ = "Hello World"  
}  
}

3

It will result in something like recursive creation of the same view

com.example.myapplication W/e.myapplicatio: at android.view.LayoutInflater.inflate[LayoutInflater.java:657] at android.view.LayoutInflater.inflate[LayoutInflater.java:532] at com.example.myapplication.databinding.SampleMyViewBinding.inflate[SampleMyViewBinding.java:44] at com.example.myapplication.MyView.[MyView.kt:23] at com.example.myapplication.MyView.[MyView.kt:17] at com.example.myapplication.MyView.[MyView.kt:-1] at java.lang.reflect.Constructor.newInstance0[Native method] at java.lang.reflect.Constructor.newInstance[Constructor.java:343] at android.view.LayoutInflater.createView[LayoutInflater.java:852] at android.view.LayoutInflater.createViewFromTag[LayoutInflater.java:1004]

2. Always give unique ids to views otherwise it will mess up.

Try to give unique ids to views in a project. Sometimes the UI you want doesn’t show up with matching ids.

3. Custom Views parent is itself that Custom View when added dynamically.

you can also try this create a chip and add it in XML with match_parent in both width and height it will take the whole space of the parent and now add it programmatically it will take the space of the content inside it. you have to set width and height programmatically.

Chủ Đề