3

I'm trying to migrate from kotlin synthetics to the recommended view binding pattern. To reduce the boiler code I chose to use the delegate approach from here.

Now I'm facing a problem, where I don't know how to solve it in an elegant way. I have two similar layouts which differentiate just from several views. For example, let's say layout_a and layout_b.

    <!-- This is just an example (layout_a) ! -->
    <LinearLayout>
        <TextView
            android:id="@+id/commonView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <TextView
            android:id="@+id/commonView2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>
    <!-- This is just an example (layout_b) ! -->
    <LinearLayout>

        <TextView
            android:id="@+id/commonView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <TextView
            android:id="@+id/commonView2"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <TextView
            android:id="@+id/specialView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

Since I don't want to code the text setter logic for these TextViews twice in my app, I created an extra singleton class that exactly maps these common views through a view object. Thanks to kotlin synthetics I was able to reference these views when I used the same id's (like commonView1 and commonView2). Since now I have to use the binding objects (LayoutABinding and LayoutBBinding in this case) I can't do this.

Sure, I could just change the visibility of the specialView1 programmatically and merge these two layouts in one, but the reason for this duplication was performance and memory efficiency. Of course the above is just an example and in my original app, I have a lot more views that would be rendered unnecessarily and waste memory space.

A possible workaround could be to use findViewById in these special cases, which is a bit meh IMO.

Is there any way to abstract these bindings?

Rahul
  • 3,293
  • 2
  • 31
  • 43
Ahmet K
  • 713
  • 18
  • 42

2 Answers2

1

You can create a custom view that wraps the common views this way you will have a single binding class.

Another way would be to use <include> to include the common views to both layouts.

georkost
  • 588
  • 6
  • 12
  • This will still render/ populate the unnecessary views and affect the heap usage. The `include` tag will also add an additional container layout on top, which is not what I want. – Ahmet K Jul 04 '21 at 19:05
  • You can use `merge` tag to use a separate layout without the need of a new container. Though I don't know if view binding knows how to handle this. – Shlomi Katriel Jul 11 '21 at 04:38
  • 1
    @ShlomiKatriel is right. To avoid having another level of nesting, you can use the `merge` tag for your shared layouts. To make editing easier in the merge-layout see `tools:parentTag`. In the include tag, you can pass-on the binding values by just using the variable names of the merge-layout, e.g. `binding:myBindingVar="@{...}"` – muetzenflo Jul 14 '21 at 07:52
1

For this case you can use ViewStub . ViewStub does not inflate the view until u call it. This will solve your performance issue.

Have two ViewStub and inflate the stub at runtime. You can bind the inflated view Like this. Once you have Binding object you can access the views directly. Just pass the data object to Binding to show data on text views. Whatever logic you have in that singleton can be used with DataBinding also.

ADM
  • 20,406
  • 11
  • 52
  • 83