在Kotlin Composable中调用JNI函数startOsc()遇未解析引用问题
解决Composable中调用
startOsc()出现Unresolved reference的问题 问题场景
在MainActivity中定义了private external fun startOsc(),但在独立的Composable组件TwoNotesView中调用时触发Unresolved reference: startOsc错误。MainActivity内部调用该函数正常,startEngine()和stopEngine()也能正常执行,JNI层实现无问题。
核心原因
Composable函数TwoNotesView处于独立作用域,无法直接访问MainActivity类的私有成员函数,必须通过合理方式将函数引用传递到Composable的作用域中。
解决方案
方案1:直接传递函数引用(最简单)
修改TwoNotesView让它接收函数类型参数,在MainActivity调用Composable时传入::startOsc:
// MainActivity中修改setContent部分 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { TwoNotesView(onReplayClick = ::startOsc) } startEngine() } // 修改TwoNotesView Composable @Composable fun TwoNotesView(onReplayClick: () -> Unit) { Column( modifier = Modifier .fillMaxSize() .background(colorResource(id = R.color.cyan)) ) { Row { Box ( modifier = Modifier .clickable { onReplayClick() // 调用传递进来的函数 } ) { AnswerButton(ImageSource = R.drawable.round_replay_24_cyan) } } } }
方案2:使用ViewModel中转(适合复杂业务场景)
如果后续有更多音频控制逻辑,建议用ViewModel封装,避免直接在Composable中依赖Activity实例:
// 创建AudioViewModel class AudioViewModel(private val startOscAction: () -> Unit) : ViewModel() { fun startOsc() { startOscAction() } } // MainActivity中初始化ViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val audioViewModel = ViewModelProvider(this, object : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { return AudioViewModel(::startOsc) as T } })[AudioViewModel::class.java] setContent { TwoNotesView(viewModel = audioViewModel) } startEngine() } // 修改TwoNotesView @Composable fun TwoNotesView(viewModel: AudioViewModel) { Column( modifier = Modifier .fillMaxSize() .background(colorResource(id = R.color.cyan)) ) { Row { Box ( modifier = Modifier .clickable { viewModel.startOsc() } ) { AnswerButton(ImageSource = R.drawable.round_replay_24_cyan) } } } }
方案3:转为静态函数(仅当逻辑允许时)
如果startOsc不需要依赖MainActivity实例,可以将其移到companion object中转为静态函数:
class MainActivity : ComponentActivity() { private external fun startEngine() private external fun stopEngine() companion object { init { System.loadLibrary("pitch_andoid") } private external fun startOsc() // 提供公开的调用入口 fun triggerStartOsc() = startOsc() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { TwoNotesView() } startEngine() } override fun onDestroy() { super.onDestroy() stopEngine() } } // 在Composable中调用 @Composable fun TwoNotesView() { Column( modifier = Modifier .fillMaxSize() .background(colorResource(id = R.color.cyan)) ) { Row { Box ( modifier = Modifier .clickable { MainActivity.triggerStartOsc() } ) { AnswerButton(ImageSource = R.drawable.round_replay_24_cyan) } } } }
验证说明
三种方案都能解决Unresolved reference问题,其中方案1最适合简单场景,方案2更符合Jetpack Compose的架构设计理念,方案3仅适用于无实例依赖的JNI函数。
内容的提问来源于stack exchange,提问作者buleva
相关产品推荐
相关产品推荐

