I can’t find out why I’m getting this error: : /Us...
# compose
c
I can’t find out why I’m getting this error: : /Users/ch/brmvuroleticsandroid/app/src/main/java/de/rocketlane/uroletics/MainActivity.kt: (18, 13): @Composable invocations can only happen from the context of a @Composable function more inside the thread…
🧵 7
r
Which line is it pointing to? Maybe mark it with a comment, since slack doesn't show which one is "line 18".
c
code:
Copy code
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            navComposeApp()
        }
    }
}

@Composable
fun navComposeApp() {
    val navController = rememberNavController()
    val actions = remember(navController) { Action(navController) }
    MaterialTheme() {
        NavHost(
            navController = navController,
            startDestination = TEST_AREA
        ) {
            composable(TEST_AREA) { TestArea(action = actions.testArea) }
        }
    }
}

object Destinations {
    const val TEST_AREA = "TEST_AREA"
}

class Action(navController: NavHostController) {
    val testArea: () -> Unit = { navController.navigate(TEST_AREA) }
    val navigateBack: () -> Unit = { navController.popBackStack() }
}

@Composable
fun TestArea(action: () -> Unit) {}
Gradle Project:
Copy code
classpath 'com.android.tools.build:gradle:7.0.0-alpha14'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32"
Gradle App:
Copy code
dependencies {
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.3.0-rc01'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.ui:ui-foundation:0.1.0-dev03'

    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

    implementation "androidx.navigation:navigation-compose:1.0.0-alpha10"

    implementation "androidx.compose.ui:ui:1.0.0-beta05"
    implementation "androidx.compose.material:material:1.0.0-beta05"
    implementation "androidx.compose.ui:ui-tooling:1.0.0-beta05"

    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
Compose works fine until I try to drop navigation on it 😕 Navcomposer, inside of main activity set Content
If you paste navcomposers conde inside of set Content you get 2 errors like these
r
I don't know. Maybe you imported the wrong
setContent
? It's an extension function. If I jump to definition, the signature looks like this:
Copy code
public fun ComponentActivity.setContent(
    parent: CompositionContext? = null,
    content: @Composable () -> Unit
) { ...
1
c
On this line, maybe it’s because it’s
=
instead of
by
?
Copy code
val actions = remember(navController) { Action(navController) }
c
Thank you all, next time I will create a sample project. Every time. It was the wrong import for setContent 😓
c
Ohhhh 🤦‍♂️
c
Extreme face palm.
c
I do find the Alt+Enter habit of imports trips me up with Compose from time to time due to name conflicts and me just hitting Enter too quickly. Like with
Color
and
Modifier
🤦‍♂️
1
Created a working sample for the future
But yes, for me, the naming of the features we need to use, and the very frequent similar names are a death trap.
Honestly I don’t quick alt tab anymore, as far as I realize at least. But I really didn’t knew we have 2 types of setContent. Is there a way to override this so I can remove the features that are currently incompatible with the style of implementation I’m using?
c
With
setContent
or the IDE?
c
I wouldn't know how to do both, but even then now I know, I can see this happening in the future so, if I could have some sort of config on IDE or a extension funcion/class that could do this. Really uncharted territory, I wouldn't know where to begin with
c
Gotcha - yeah maybe something we can look into on the autocomplete side. @Adam Powell does this sound familiar with
setContent
?
c
You, I would see a solution forking the library I don't want and changing the method name. But this looks like a very long stretch for something I could have a post it in my monitor. 😂
If the library could even be extended, I believe this is directly from androidX
a
where are you seeing two separate definitions of
setContent
?
c
One is from here: package androidx.ui.core The other here: package androidx.activity.compose
From wrapper
Copy code
fun Activity.setContent(
    content: @Composable() () -> Unit
): CompositionContext? {
    val composeView = window.decorView
        .findViewById<ViewGroup>(android.R.id.content)
        .getChildAt(0) as? AndroidComposeView
        ?: AndroidComposeView(this).also { setContentView(it) }

    // If this value is inlined where it is used, an error that includes 'Precise Reference:
    // kotlinx.coroutines.Dispatchers' not instance of 'Precise Reference: androidx.compose.Ambient'.
    val coroutineContext = Dispatchers.Main
    return Compose.composeInto(composeView.root, this) {
        WrapWithAmbients(composeView, this, coroutineContext, content)
    }
}
From ComponentActivity
Copy code
public fun ComponentActivity.setContent(
    parent: CompositionContext? = null,
    content: @Composable () -> Unit
) {
    val existingComposeView = window.decorView
        .findViewById<ViewGroup>(android.R.id.content)
        .getChildAt(0) as? ComposeView

    if (existingComposeView != null) with(existingComposeView) {
        setParentCompositionContext(parent)
        setContent(content)
    } else ComposeView(this).apply {
        // Set content and parent **before** setContentView
        // to have ComposeView create the composition on attach
        setParentCompositionContext(parent)
        setContent(content)
        // Set the view tree owners before setting the content view so that the inflation process
        // and attach listeners will see them already present
        setOwners()
        setContentView(this, DefaultActivityContentLayoutParams)
    }
}
I mean it’s obvious that I would like to use compose but the error I got didn’t led me to believe the import was wrong, it seemed appropriate. The error:
@Composable invocations can only happen from the context of a @Composable function
i
I think the problem is that you still have the
androidx.ui:ui-foundation:0.1.0-dev03
dependency - you shouldn't be using any
0.1.0-dev
version of Compose artifacts anymore. Removing that will also remove the ambiguity
1
c
Thank you Ian, which leads me to a follow up question, do we have a testable repo that can be used as a guideline for combination of official android libraries? I’m always ping ponging around trying to understand what should be matched with what.
i
The 'Declaring dependencies' section of each release notes page is updated on every release with what dependencies you should be using: https://developer.android.com/jetpack/androidx/releases
🔥 1
❤️ 1
c
Awesome.
Thank you very much Ian.