You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android库网络请求后向应用传数据及关闭Compose UI方法咨询

解决方案

核心思路

由于库内的someData和ViewModel是internal(仅库内可见),不能直接跨模块暴露给应用层。我们需要通过公开的结果类型+回调机制实现数据传递,同时利用Compose状态控制库UI的显示/隐藏。

1. 库模块:定义公开的跨模块通信类型

先在库内创建对外可见的结果封装类,用来中转内部数据,避免暴露internal成员:

// 库模块 - 公开的结果密封类,用于跨模块传递状态
sealed class LibraryRequestResult {
    data class Success(val id: String, val name: String) : LibraryRequestResult()
    data class Error(val errorMsg: String) : LibraryRequestResult()
    object Cancelled : LibraryRequestResult()
}

// 可选:也可以定义公开的数据类,代替拆字段传递
// data class PublicSomeData(val id: String, val name: String)

2. 库模块:内部ViewModel处理请求并发送结果

库内的internal ViewModel负责网络请求,用StateFlow管理内部结果状态:

// 库模块 - internal ViewModel,仅库内可访问
internal class LibraryViewModel : ViewModel() {
    private val _internalResult = MutableStateFlow<InternalResult>(InternalResult.Idle)
    val internalResult = _internalResult.asStateFlow()

    // 库内专用的结果密封类,internal修饰
    internal sealed class InternalResult {
        object Idle : InternalResult()
        data class DataLoaded(val data: someData) : InternalResult()
        data class RequestFailed(val msg: String) : InternalResult()
        object UserCancelled : InternalResult()
    }

    // 发起网络请求(Retrofit+Moshi逻辑)
    fun startNetworkRequest() {
        viewModelScope.launch {
            try {
                val apiResponse = yourRetrofitService.fetchData()
                val parsedData = apiResponse.body() ?: throw IllegalStateException("空响应")
                _internalResult.value = InternalResult.DataLoaded(parsedData)
            } catch (e: Exception) {
                _internalResult.value = InternalResult.RequestFailed(e.message ?: "请求失败")
            }
        }
    }

    // 用户主动取消时调用
    fun onCancel() {
        _internalResult.value = InternalResult.UserCancelled
    }
}

3. 库模块:提供公开的Compose入口

封装库的UI和ViewModel逻辑,对外仅暴露一个接收结果回调的Composable函数:

// 库模块 - 公开的Compose入口,应用层通过这个函数启动库UI
@Composable
fun LibraryRequestUI(onResult: (LibraryRequestResult) -> Unit) {
    val libraryViewModel = viewModel<LibraryViewModel>()

    // 监听内部ViewModel的结果流,转换为公开类型后传给应用
    LaunchedEffect(libraryViewModel) {
        libraryViewModel.internalResult.collect { internalState ->
            when (internalState) {
                is LibraryViewModel.InternalResult.DataLoaded -> {
                    // 将internal的someData转换为公开结果
                    onResult(LibraryRequestResult.Success(internalState.data.id, internalState.data.name))
                }
                is LibraryViewModel.InternalResult.RequestFailed -> {
                    onResult(LibraryRequestResult.Error(internalState.msg))
                }
                LibraryViewModel.InternalResult.UserCancelled -> {
                    onResult(LibraryRequestResult.Cancelled)
                }
                else -> {} // 忽略Idle状态
            }
        }
    }

    // 库的Compose UI实现
    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Button(onClick = libraryViewModel::startNetworkRequest) {
            Text("发起请求")
        }
        Spacer(modifier = Modifier.height(16.dp))
        Button(onClick = libraryViewModel::onCancel) {
            Text("取消")
        }
    }
}

4. 应用模块:调用库并处理结果

应用层通过状态变量控制库UI的显示,在回调中接收结果、关闭库UI并传递给应用ViewModel:

// 应用模块 - 主界面Composable
@Composable
fun AppMainScreen() {
    var showLibraryUI by remember { mutableStateOf(false) }
    val appViewModel = viewModel<AppViewModel>()

    Column(modifier = Modifier.fillMaxSize(), padding = PaddingValues(16.dp)) {
        Button(onClick = { showLibraryUI = true }) {
            Text("启动库请求")
        }

        // 根据状态显示/隐藏库UI
        if (showLibraryUI) {
            LibraryRequestUI(onResult = { result ->
                // 关闭库UI
                showLibraryUI = false
                // 处理结果并传给应用ViewModel
                when (result) {
                    is LibraryRequestResult.Success -> {
                        appViewModel.processLibraryData(result.id, result.name)
                    }
                    is LibraryRequestResult.Error -> {
                        appViewModel.showErrorToast(result.errorMsg)
                    }
                    LibraryRequestResult.Cancelled -> {
                        // 处理用户取消逻辑
                    }
                }
            })
        }
    }
}

// 应用模块 - 应用层ViewModel
class AppViewModel : ViewModel() {
    fun processLibraryData(id: String, name: String) {
        // 业务逻辑:保存数据、更新UI状态等
    }

    fun showErrorToast(msg: String) {
        // 错误提示逻辑
    }
}

关键说明

  • 全程不暴露库内的internal成员,保证模块封装性;
  • 用StateFlow实现库内ViewModel的状态分发,结合LaunchedEffect在Compose中监听结果;
  • 应用层通过Boolean状态控制库UI的显示/隐藏,回调触发后自动关闭库界面。

内容的提问来源于stack exchange,提问作者tariqebadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 06:20:59