Sachin Varma
Sachin Varma

Reputation: 2235

java.lang.IllegalStateException: Composition requires an active composition context (Android Jetpack Compose)

Trying to show an AlertDialog using Jetpack Compose, but App is crashing while calling the AlertDialog function with error as

java.lang.IllegalStateException: Composition requires an active composition context

Please find the code below,

@Composable
fun homeScreenCompose() {

    Align(
        alignment = Alignment.Center
    ) {
        Column(
            arrangement = Arrangement.Center,
            modifier = Spacing(16.dp),
            children = {

                Button(
                    modifier = Height(50.dp) wraps Expanded,
                    text = "Alert Dialog", onClick = {
                        showAlertDialog()
                    }, style = OutlinedButtonStyle(
                        Border(color = Color.Red, width = 1.dp),
                        shape = RoundedCornerShape(50), //50% percent
                        contentColor = Color.Red,
                        color = Color.White,
                        elevation = Dp(4f)
                    )
                )
            }
        )
    }

}

@Composable
fun showAlertDialog() {
    val openDialog = +state { true }
    if (openDialog.value) {
        AlertDialog(
            onCloseRequest = {
            },
            title = {
                Text(text = "Logout")
            },
            text = {
                Text("Are you sure you have to logout?")
            },
            confirmButton = {
                Button("Yes", onClick = {
                    openDialog.value = false
                })
            },
            dismissButton = {
                Button("No", onClick = {
                    openDialog.value = false
                })
            },
            buttonLayout = AlertDialogButtonLayout.Stacked
        )
    }

}

Not able to figure out why it is crashing and what's the solution for this, any help will be appreciated.

Thank you.

Upvotes: 2

Views: 4866

Answers (1)

Anas Mehar
Anas Mehar

Reputation: 2835

  1. Creates a data class for the state model, and it does not have to be marked with the @Model annotation.
  2. The initial state itself is created inside the @Composable function using + state.
  3. The visibility of the dialog is determined by the visible property of the model obtained by calling the value property.
  4. This property can also be set to a new immutable object, as happens in the onClick of both buttons. The first hides itself, the second - closes the dialogue. The dialog can be reopened by clicking on the Ok button, defined inside the same @Composable function.

When trying to make a state outside this function, an error occurs:

java.lang.IllegalStateException: Composition requires an active composition context.

The context can be obtained by assigning the value of the setContent {} function in onCreateView, but how to use it, for example, in Presenter or another class other than Fragment or Activity, for changing the state is still unclear.

Check example below

 data class DialogVisibleModel(val visible: Boolean, val dismissPushed: Boolean = false)
    ...
 @Composable
 fun homeScreenCompose() {

   Column {
        SideBySideAlertDialogSample()
   }

 }

@Composable
fun SideBySideAlertDialogSample() {
    val openDialog = +state { DialogVisibleModel(false) }

    Button(text = "Ok", onClick = { openDialog.value = DialogVisibleModel(true) })

    if (openDialog.value.visible) {
        AlertDialog(
            onCloseRequest = {
                // Because we are not setting openDialog.value to false here,
                // the user can close this dialog only via one of the buttons we provide.
            },
            title = {
                Text(text = "Title")
            },
            text = {
                Text("This area typically contains the supportive text" +
                        " which presents the details regarding the Dialog's purpose.")
            },
            confirmButton = {
                Button("Confirm", onClick = {
                    openDialog.value = DialogVisibleModel(false)
                })
            },
            dismissButton = {
                if (!openDialog.value.dismissPushed)
                    Button("Dismiss", onClick = {
                        openDialog.value = DialogVisibleModel(true, true)
                    })
                else {
                    //hidden
                }
            },
            buttonLayout = AlertDialogButtonLayout.SideBySide
        )
    }
}

Upvotes: 3

Related Questions