如何让ConfirmationDialog同步返回结果?多场景复用方案咨询
问题解决方案
一、关于同步返回对话框结果的可行性
直接通过val returnValue = dialog.show()同步获取结果不可行,因为Android对话框是异步交互组件——UI操作必须在主线程执行,同步阻塞主线程会触发ANR(Application Not Responding),违反Android的UI线程规则。所有用户交互(比如点击确认/取消)都是异步回调触发的,无法直接同步返回结果。
二、优雅复用确认对话框的实现方案
1. 用Kotlin协程封装异步结果(推荐)
借助CompletableDeferred将回调式的异步结果转为挂起函数,实现类似同步的写法,同时不阻塞主线程:
步骤1:封装通用确认对话框的挂起函数
suspend fun showConfirmationDialog( context: Context, title: String, message: String ): Boolean { val deferred = CompletableDeferred<Boolean>() AlertDialog.Builder(context) .setTitle(title) .setMessage(message) .setPositiveButton("确认") { _, _ -> deferred.complete(true) } .setNegativeButton("取消") { _, _ -> deferred.complete(false) } .setOnCancelListener { deferred.complete(false) } .show() return deferred.await() }
步骤2:在RecyclerView的Adapter中调用(需在协程作用域)
在Adapter的点击事件里,通过lifecycleScope或者viewModelScope启动协程:
// 假设Adapter持有LifecycleOwner引用(比如从Activity/Fragment传入) button.setOnClickListener { lifecycleOwner.lifecycleScope.launch { val isConfirmed = showConfirmationDialog( context = itemView.context, title = "删除确认", message = "确定要删除这条数据吗?" ) if (isConfirmed) { // 执行当前场景的操作,比如删除数据 deleteItem(position) } } }
这种方式不需要在MainActivity中标记操作类型,每个场景直接在点击回调里处理自己的逻辑,完全解耦。
2. 用高阶函数传递回调逻辑
如果不想用协程,可以把确认后的操作作为高阶函数传入对话框,直接在对话框的按钮回调中执行:
步骤1:封装带回调的通用对话框
fun showConfirmationDialog( context: Context, title: String, message: String, onConfirm: () -> Unit, onCancel: () -> Unit = {} ) { AlertDialog.Builder(context) .setTitle(title) .setMessage(message) .setPositiveButton("确认") { _, _ -> onConfirm() } .setNegativeButton("取消") { _, _ -> onCancel() } .setOnCancelListener { onCancel() } .show() }
步骤2:在Adapter中调用
button.setOnClickListener { showConfirmationDialog( context = itemView.context, title = "编辑确认", message = "确定要修改这条数据吗?", onConfirm = { // 执行编辑操作 editItem(position) }, onCancel = { // 可选:取消后的逻辑 } ) }
这种写法同样不需要在MainActivity中维护状态变量,每个场景的操作逻辑直接内联传递,清晰且复用性强。
3. 优化原接口监听方案
如果坚持用接口方式,也可以通过场景枚举+接口携带参数来替代主Activity的变量标记:
// 定义操作场景枚举 enum class DialogAction { DELETE, EDIT, SHARE } // 定义带场景参数的接口 interface DialogCallback { fun onActionConfirmed(action: DialogAction, position: Int) } // 在Adapter中调用时传入场景 button.setOnClickListener { showConfirmationDialog( context = itemView.context, title = "分享确认", message = "确定要分享这条内容吗?", callback = activity as DialogCallback, action = DialogAction.SHARE, position = position ) } // MainActivity实现接口时根据场景处理 override fun onActionConfirmed(action: DialogAction, position: Int) { when(action) { DialogAction.DELETE -> deleteItem(position) DialogAction.EDIT -> editItem(position) DialogAction.SHARE -> shareItem(position) } }
这种方式虽然还是用接口,但通过枚举和参数明确操作类型,不需要在Activity中维护额外的标记变量,比原方案更清晰。
内容的提问来源于stack exchange,提问作者Owlon
相关产品推荐
相关产品推荐

