Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set Android DataBinding in nested layouts

I was just reading about data binding feature in android. I was trying to bind a view from a nested layout. My activity is android's default template of DrawerMenuActivity and it has content_my_activity layout nested inside activity_my_activity layout.

I have 3 auto generated binding classes. MyActivityBinding, AppBarMyActivityBinding and ContentMyActivityBinding.

I tried initialising all 3 class as below:

MyActivity.java

MyActivityBinding activityBinding;
AppBarMyActivityBinding appBarBinding;
ContentMyActivityBinding contentBinding;

protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);

    activityBinding = DataBindingUtils.setContentView(this, 
                               R.layout.activity_my_activity);
    appBarBinding = DataBindingUtils.setContentView(this, 
                               R.layout.app_bar_my_activity);
    contentBinding = DataBindingUtils.setContentView(this, 
                               R.layout.content_my_activity);

    setName();
}

private void setName(){
    contentBinding.setFirstName("Omkar");
}

But it throws RuntimeException as below:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example, PID: 18305
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.userInterface.activity.MyActivity}: android.view.InflateException: Binary XML file line #35: Binary XML file line #27: Error inflating class fragment
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
    at android.app.ActivityThread.access$900(ActivityThread.java:154)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5443)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
 Caused by: android.view.InflateException: Binary XML file line #35: Binary XML file line #27: Error inflating class fragment
    at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
    at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:280)
    at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
    at android.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:276)
    at com.example.userInterface.activity.MyActivity.onCreate(MyActivity.java:88)
    at android.app.Activity.performCreate(Activity.java:6259)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490) 
    at android.app.ActivityThread.access$900(ActivityThread.java:154) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5443) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
 Caused by: android.view.InflateException: Binary XML file line #27: Error inflating class fragment
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:782)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:835)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:838)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
    at android.view.LayoutInflater.parseInclude(LayoutInflater.java:971)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:831)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
    at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:280) 
    at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140) 
    at android.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:276) 
    at com.example.userInterface.activity.MyActivity.onCreate(MyActivity.java:88) 
    at android.app.Activity.performCreate(Activity.java:6259) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490) 
    at android.app.ActivityThread.access$900(ActivityThread.java:154) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5443) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
 Caused by: java.lang.IllegalArgumentException: Binary XML file line #27: Duplicate id 0x7f0e0081, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.SupportMapFragment
    at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2416)
    at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:120)
    at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:374)
    at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:33)
    at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:75)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:754)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:835) 
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
    at android.view.LayoutInflater.parseInclude(LayoutInflater.java:971) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:831) 
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:515) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
    at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:280) 
    at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140) 
    at android.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:276) 
    at com.example.userInterface.activity.MyActivity.onCreate(MyActivity.java:88) 
    at android.app.Activity.performCreate(Activity.java:6259) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490) 
    at android.app.ActivityThread.access$900(ActivityThread.java:154) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5443) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 

How do I bind view from content_my_activity in MyActivity.java class, any help is appreciated.

Thanks.

like image 771
Omkar Avatar asked Jul 19 '16 17:07

Omkar


People also ask

Can I use both databinding and ViewBinding?

Data binding includes everything that ViewBinding has, so it wasn't designed to work side by side with View binding. The biggest issue is the naming conflict between the generated classes. Both ViewBinding and DataBonding would want to generate the class MainLayoutBinding for the layout main_layout. xml .

Is databinding better than findViewById method?

findViewById(R. id. some_id) to retrieve Views in code. ViewBinding works similarly, but, in addition to just adding the IDs into a global list, it parses more information from XML and generates code for each layout file.

Which is the correct way to reference bound data in the XML layout?

Layout Binding expressions Expressions in the XML layout files are assigned to a value of the attribute properties using the “ @{} " syntax. We just need to use the basic syntax @{} in an assignment expression. Expressions can be used for many purposes depending on your requirement.


2 Answers

DataBindingUtils.setContentView() does exactly how it is named: It sets the current view to the given parameter. I don't think you want your AppBar as the whole view, or do you?

Nevertheless, I assume that you include your layouts in your layout_activity_main.xml. George Mount has written a whole blog post about this feature. The code examples are from this post.

The first example would be your layout_activity_main.xml (Or however you have named it), where you include your AppBar, your Content and so on.

hello_world.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

        <TextView
                android:id="@+id/hello"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
        <include
                android:id="@+id/world1"
                layout="@layout/included_layout"/>
        <include
                android:id="@+id/world2"
                layout="@layout/included_layout"/>
    </LinearLayout>
</layout>


included_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/world"/>
</layout>

Now that the used layouts are clear, you'll need to jump into your ActivityMain, initialize the DataBinding and access your fields:

//This works if you have used a variable in your <data> tag and you have built your project afterwards, if you don't have an activity
HelloWorldBinding binding = HelloWorldBinding.inflate(getLayoutInflater());

 //if you have an activity, you can use setContentView from the DataBindingUtils. Don't forget to delete the generic setContentView
HelloWorldBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_my_activity);


//Once you have accomplished the above, you can access your data-bound fields like this:
binding.hello.setText(“Hello”);
binding.world1.world.setText(“First World”);
binding.world2.world.setText(“Second World”);

It is important to set Ids to your <include> tags to access them correctly i your Activity.

like image 124
yennsarah Avatar answered Oct 08 '22 06:10

yennsarah


One can pass the objects in XML ... the xmlns:bind namespace is required (similar to xmlns:app).

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/apk/res-auto">
    
   <data>
       <variable name="user" type="com.example.User"/>
   </data>

   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

       <include
           layout="@layout/name"
           bind:user="@{user}"/>

       <include
           layout="@layout/contact"
           bind:user="@{user}"/>

   </LinearLayout>

</layout>

source of the example: Layouts and binding expressions.

like image 44
Martin Zeitler Avatar answered Oct 08 '22 06:10

Martin Zeitler