Jetpack Compose选取文件触发异常:Launcher has not been initialized
问题解决
错误原因
直接在Composable初始化阶段调用pickFileLauncher.launch(),此时Launcher还未完成与Composable生命周期的绑定初始化,导致抛出Launcher has not been initialized异常。另外代码还存在隐藏问题:通过GetContent获取的Uri是content://协议,不能直接用getPath()转换为File对象,会引发文件找不到的错误。
修复方案
1. 正确触发Launcher的时机
不要在Composable根作用域直接调用launch,而是通过**用户交互(比如按钮点击)或者LaunchedEffect(特定条件下触发一次)**启动文件选择器。
2. 正确读取Uri对应的文件内容
使用ContentResolver打开输入流,而非直接通过File路径读取。
完整修复代码
@Composable fun FilePickerScreen() { // 存储读取到的行列表 val lineList = remember { mutableStateListOf<String>() } val context = LocalContext.current val pickFileLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.GetContent() ) { fileUri -> fileUri?.let { uri -> // 使用ContentResolver获取输入流,use函数自动管理资源关闭 context.contentResolver.openInputStream(uri)?.use { inputStream -> inputStream.bufferedReader().forEachLine { line -> lineList.add(line) } } } } Column(modifier = Modifier.padding(16.dp)) { // 通过按钮点击触发文件选择 Button(onClick = { pickFileLauncher.launch("*/*") }) { Text("选择文件") } // 展示读取到的内容 LazyColumn(modifier = Modifier.weight(1f)) { items(lineList) { line -> Text(text = line, modifier = Modifier.padding(vertical = 4.dp)) } } } }
补充说明
rememberLauncherForActivityResult必须在Composable函数内声明,不能在异步回调或非Composable代码中创建。- 如果需要在Composable启动时自动打开文件选择器,可使用
LaunchedEffect(Unit)包裹launch调用,确保在Composable初始化完成后执行:
LaunchedEffect(Unit) { pickFileLauncher.launch("*/*") }
内容的提问来源于stack exchange,提问作者Sina
相关产品推荐
相关产品推荐

