Android Studio中TrivialDriveRepository创建Dialog报Context错误如何解决
问题解决方法
报错原因
普通Dialog必须依附带主题的Activity类型Context才能正常显示,你在Repository中使用Application Context创建Dialog时,由于Application没有对应界面主题,就会触发android.content.Context.getTheme相关崩溃。同时Repository属于数据层,本身不应该处理UI逻辑,也不应该持有任何UI相关的Context,既不符合分层规范,还有内存泄漏风险。
调整步骤
你不需要修改原有架构的逻辑,利用项目本身已有的allMessages单事件LiveEvent做事件通知即可,调整分为两步:
- 移除Repository中的Dialog代码,替换为事件发送
- 在UI层(Activity/Fragment)监听事件,触发弹窗
1. 修改TrivialDriveRepository代码
找到setupMessagesSingleMediatorLiveEvent方法中SKU_INFINITE_GAS_MONTHLY的分支,删除所有Dialog相关代码,改成发送事件即可:
case SKU_INFINITE_GAS_MONTHLY: billingDataSource.refreshPurchasesAsync(); // 新增自定义事件ID,需要先在strings.xml中添加对应字符串资源,仅做事件标识用 allMessages.setValue(R.string.event_show_monthly_sub_congrats); break;
顺便修正你原代码中SKU_INFINITE_GAS_YEARLY分支位置错误的问题,把它移到switch的同级分支下即可。
2. 在Activity中监听事件弹窗
在你触发支付、或者处于前台的Activity中监听allMessages,收到对应事件后再用Activity的Context创建弹窗:
// 此处this为Activity实例 trivialDriveRepository.allMessages.observe(this, messageResId -> { if (messageResId == R.string.event_show_monthly_sub_congrats) { final Dialog dialog = new Dialog(this); dialog.setContentView(R.layout.activity_info); dialog.setCancelable(false); TextView text = dialog.findViewById(R.id.text); text.setText(R.string.premium_activity_page_premium_membership_title); TextView yorum = dialog.findViewById(R.id.yorumsatiri); yorum.setText(R.string.premium_activity_page_show_dialog_congrats_message_text); Button yes = dialog.findViewById(R.id.yes); yes.setOnClickListener(v -> { // 处理按钮点击逻辑,比如关闭弹窗 dialog.dismiss(); }); dialog.show(); } else { // 原有其他消息的处理逻辑,比如Toast提示 Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show(); } });
注意事项
- 所有UI相关操作都要放在UI层处理,数据层仅负责业务逻辑和事件通知,不要在Repository、ViewModel中持有Activity Context
- 项目自带的
SingleMediatorLiveEvent属于单消费事件,不会出现支付成功后多次回调弹窗的问题,符合使用场景
内容的提问来源于stack exchange,提问作者Nazif
相关产品推荐
相关产品推荐

