2

So I have this structure that I wanted to replace the working code with viewBinding instead of findViewById<>

abstract class ParentActivity: AppCompatActivity() 

class ChildActivity: ParentActivity() 

activity_parent.xml is a layout that contain a placeholder for a dynamically replaced child layout using setContentView override below:

So in ParentActivity.kt

abstract class ParentActivity : AppCompatActivity()
    override fun setContentView(layoutResID: Int) {
        val parent = LayoutInflater.from(this).inflate(R.layout.activity_parent, null)
        LayoutInflater.from(this).inflate(layoutResID, parent.findViewById(R.id.abstractViewContainer) as androidx.coordinatorlayout.widget.CoordinatorLayout, true)
        super.setContentView(parent)
    }
     
    // ... Shared code

}

activity_parent.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    tools:context=".nestedActivity.ParentActivity">

    <TextView
        android:id="@+id/parentTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello I am Parent Activity"
        />
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:id="@+id/abstractViewContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/parentTextView">

</LinearLayout>

ChildActivity.kt

class ChildActivity : ParentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_child)
    }
}

Is there a way to use ViewBinding instead of the old solution here?

This code is more than 10 years ago, today I would just use fragments and nav_graph (or just compose) but here I need to keep the nested activites architecture because of legacy implication of parent activity over thousands of other activites.

Solutions like this : https://stackoverflow.com/a/64461332/2474454 won't apply to my case, I want to fusion the ActivityParentBinding with ActivityChildBinding dynamically according to the child.

Akhu
  • 207
  • 2
  • 13
  • You can't fuse bindings because bindings are generated at compile time. Unfortunately, bindings do not generate interfaces, or we could easily fuse the two interfaces by delegation into one class. Also, something to consider regarding the base Activity concept: https://stackoverflow.com/a/72994918/506796 And consider that it is poor encapsulation for a child class to need to directly touch the views (binding) of the parent class. All the more reason to use composition instead of inheritance for this specific case. – Tenfour04 Sep 01 '23 at 19:00

1 Answers1

0

Looks like that answer is close. I think all you need is a ViewGroup.addView().

How about the following. (Not sure if you really need the CoordinatorLayout from your example; could replace it with a FrameLayout if you don't need the extra support)

// Copyright 2023 Google LLC.
// SPDX-License-Identifier: Apache-2.0

abstract class ParentActivity : AppCompatActivity() {
    private lateinit var binding: ActivityParentBinding // for parent stuff

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityParentBinding.inflate(layoutInflater)
        binding.abstractViewContainer.addView(createContentView()) // add the child
        setContentView(binding.root)

        // ...
    }

    abstract fun createContentView(): View
}

class ChildActivity: ParentActivity() {
    private lateinit var binding: ActivityChildBinding // for child stuff

    override fun createContentView(): View {
        binding = ActivityChildBinding.inflate(layoutInflater)
        return binding.root
    }
}
Scott Stanchfield
  • 29,742
  • 9
  • 47
  • 65