Abhimanyu
06/13/2024, 7:11 PM@Composable
fun ScreenComposable() {
val handleUri = { uri: Uri ->
// Some code
}
val openDocumentResultLauncher: ManagedActivityResultLauncher<Array<String>, Uri?> = rememberLauncherForActivityResult(
contract = ActivityResultContracts.OpenDocument(),
) { uri ->
uri?.let {
handleUri()
}
}
// openDocumentResultLauncher is used like this,
val object = remember {
SomeClass(
openDocument = {
openDocumentResultLauncher.launch(arrayOf(MimeTypeConstants.JSON))
},
)
}
}
In this code, handleUri
has to be defined before openDocumentResultLauncher
.
Can I rewrite this code in a way that handleUri
is passed as a parameter (dependency) to openDocumentResultLauncher
.
openDocument
in SomeClass
will provide the code for handleUri
.Ian Lake
06/14/2024, 3:59 AMIan Lake
06/14/2024, 4:09 AMrememberSaveable { UUID.randomUUID().toString() }
part) - that's how this actually reconnects consistently
2. Getting the ActivityResultRegistry
using the LocalActivityResultRegistryOwner
3. Calling register
(which is what requires your handleUri
) and unregister
in a DisposableEffect
such that the launcher only exists as long as it exists in composition
Technically, those are all pieces you can do yourself, in any place you want. However, I don't think you can do all of that within the remember
of SomeClass
Abhimanyu
06/14/2024, 4:25 AMhandleUri
inside SomeClass
.
Currently, createDocument
callback of SomeClass
will expose the handler to the parent Composable.
createDocument = { handler: (uri: Uri) -> Unit ->
createDocumentResultLauncher.launch(MimeTypeConstants.JSON)
},
But, I could not figure our how to use the handler
now.
Can you please help thank you color .Abhimanyu
06/14/2024, 4:27 AMrememberLauncherForActivityResult
into the createDocument
as it does not have Composable scope.
Also, the SomeClass
is Compose independent, so I can't make createDocument
into a Composable lambda.Timo Drick
06/17/2024, 12:34 PM@Composable
fun rememberFilePicker(): FilePickerState {
val state = remember { MutableFilePickerState() }
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.OpenDocument(),
onResult = { uri: Uri? ->
state.selectedUri = uri
}
)
state.launcher = launcher
return state
}
interface FilePickerState {
val selectedUri: Uri?
fun launchFilePickerIntent(filter: Array<String>)
}
private class MutableFilePickerState() : FilePickerState {
var launcher: ManagedActivityResultLauncher<Array<String>, Uri?>? = null
override var selectedUri: Uri? by mutableStateOf(null)
override fun launchFilePickerIntent(filter: Array<String>) {
checkNotNull(launcher).launch(filter)
}
}
Usage in compose is than as follows:
val filePicker = rememberFilePicker()
val selectedAudioUri = filePicker.selectedUri
if (selectedAudioUri != null) {
AudioPane(
modifier = Modifier.fillMaxSize(),
audioUri = selectedAudioUri
)
} else {
Button(onClick = { filePicker.launchFilePickerIntent(arrayOf("audio/*")) }) {
Text("Select music file")
}
}
Not exactly what you ask for. But i am sure you can change the code that it will fit you needs.
So you could add a lambda parameter to the remember function that is called when the uri is selected.