Search code examples
androidandroid-jetpack-compose

Android Composable Inheritance?


I have an android application with 1 MainActivity.

There is a list of composable files that a navigation menu uses that launch the respective composable. We created a class file for each composable but it only contains 2 composable functions.


package com.example.Scanner.screens

import ... 
    @Composable
    fun Screen1(modifier: Modifier = Modifier) {
        Text(text = "hi")
        }

@Preview(showBackground = true)
@Composable
fun Screen1Preivew() {
    Scanner1Theme {
        Screen1()
    }
}

I want to make another class that all these composable inherit. So i don't have to copy paste the code around. I might have created all the composables wrong because I do not see a class definition or a way to inherit anything.

@Composable
fun SystemBroadcastReceiver(
    systemAction: String,
    onSystemEvent: (intent: Intent?) -> Unit
) {
    // Grab the current context in this part of the UI tree
    val context = LocalContext.current

    // Safely use the latest onSystemEvent lambda passed to the function
    val currentOnSystemEvent by rememberUpdatedState(onSystemEvent)

    // If either context or systemAction changes, unregister and register again
    DisposableEffect(context, systemAction) {
        val intentFilter = IntentFilter(systemAction)
        val broadcast = object : BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                currentOnSystemEvent(intent)
            }
        }

        context.registerReceiver(broadcast, intentFilter)

        // When the effect leaves the Composition, remove the callback
        onDispose {
            context.unregisterReceiver(broadcast)
        }
    }
}

The composable doesn't seem like an object but a function outside of a class.

Any help would be appreciated.


Solution

  • Composable functions are top-level functions, not classes, inheritance isn't available with compose. Composables are stateless because there is no object that is stored anywhere. This is one of the central design principles that led to the development of the Compose framework. State must instead be explicitly stored as a State that is automatically observed by the snapshot system that compose uses under the hood, or it must be implemented outside of your composables (in the view model, for example).

    The alternative to inheritance is composition. Let's assume all your screens contain a header and a footer:

    @Composable
    fun Screen1() {
        Column {
            Text(text = "Header")
            Text(text = "Screen1 content")
            Text(text = "Footer")
        }
    }
    
    @Composable
    fun Screen2() {
        Column {
            Text(text = "Header")
            Text(text = "Screen2 content")
            Text(text = "Footer")
        }
    }
    

    Instead of repeating that for each screen, you could extract the common components in a separate composable and assemble it like this:

    @Composable
    fun Screen1() = Screen {
        Text(text = "Screen1 content")
    }
    
    @Composable
    fun Screen2() = Screen {
        Text(text = "Screen2 content")
    }
    
    @Composable
    fun Screen(
        content: @Composable () -> Unit,
    ) {
        Column {
            Text(text = "Header")
            content()
            Text(text = "Footer")
        }
    }
    

    This is how you avoid code duplication in Compose.