Skip to content

Latest commit

 

History

History
72 lines (57 loc) · 2.76 KB

ViewBindingDelegates.md

File metadata and controls

72 lines (57 loc) · 2.76 KB

ViewBinding delegates

In order to reduce boilerplate and simplify work with view binding, it's often suggested to use special delegates that provide a ViewBinding object and automatically clear the associated property when the view is destroyed.

There are many libraries and articles that describe how to create them and all these solutions use a similar principle, which you can easily implement using the lifecycleAware delegate (for activities) or the viewLifecycleAware delegate (for fragments).

So, for example, you can implement viewBinding using reflection and the ViewBinding.bind method:

// Creates `ViewBinding` instance via `ViewBinding.bind` method (reflective)
inline fun <reified T : ViewBinding> Fragment.viewBinding() = viewLifecycleAware(
    initializer = {
        val bindMethod = T::class.java.getMethod("bind", View::class.java)
        bindMethod.invoke(null, requireView()) as T
    }
)

// Creates `ViewBinding` instance via `ViewBinding.bind` method (reflective)
inline fun <reified T : ViewBinding> ComponentActivity.viewBinding() = lifecycleAware(
    initializer = {
        val bindMethod = T::class.java.getMethod("bind", View::class.java)
        val view = findViewById<ViewGroup>(android.R.id.content).getChildAt(0)
        bindMethod.invoke(null, view) as T
    }
)

// ...

class SampleFragment : Fragment(R.layout.sample_fragment) {

    private val binding: SampleFragmentBinding by viewBinding()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.vMessage.text = "Test message"
    }
}

And this is how the implementation of viewBinding for an activity can look like using the ViewBinding.inflate method and without using reflection:

// Creates `ViewBinding` instance via `ViewBinding.inflate` method (non-reflective)
fun <T : ViewBinding> ComponentActivity.viewBinding(inflateMethod: (LayoutInflater) -> T) =
    lifecycleAware(
        initializer = { inflateMethod(layoutInflater) }
    )

// ...

class SampleActivity : AppCompatActivity() {

    private val binding by viewBinding(SampleActivityBinding::inflate)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
    }
}