I am attempting to fetch a contact number and name, but I am encountering an error that states:
@Composable invocations can only happen from the context of a @Composable function.
how to resolve this issue?
data class Contact(val name: String, val phoneNumber: String)
@Composable
fun ContactList(){
val context = LocalContext.current
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
// Permission is granted, fetch the contacts
val contacts = fetchContacts(context)
LazyColumn {
items(contacts) { contact ->
Text(text = "Name: ${contact.name}, Phone: ${contact.phoneNumber}")
Spacer(modifier = Modifier.padding(10.dp))
}
}
} else {
// Handle the case when the user denies the permission
}
}
// Request permission to read contacts
launcher.launch(Manifest.permission.READ_CONTACTS)
}
private fun fetchContacts(context: Context): List<Contact> {
val contacts = mutableListOf<Contact>()
val cursor = context.contentResolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
null,
null,
null
)
cursor?.use {
while (it.moveToNext()) {
val name = it.getString(it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
val phoneNumber = it.getString(it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
contacts.add(Contact(name, phoneNumber))
}
}
return contacts
}
rememberLauncherForActivityResult(...)
takes a second parameteronResult
which is just a standard callback (not a composable one). You are getting the error as you are trying to call a composable function (LazyList { ... }
) where a normal one was expected. The way I'd handle this situation is to change some state variable either locally, or in the viewmodel, whenonResult
fires - and then listen to changes to this variable in the UI where you will then display the lazy list