Android MainActivity底部弹窗传值至第二Activity报接口空指针问题
问题根因
报错的核心原因是两个基础写法错误:
- 你在ProductInformationActivity里通过
new MainActivity()手动创建Activity实例的写法完全不符合Android组件运行规则。Activity是由系统ActivityManager统一创建、管理生命周期的系统组件,你手动new出来的只是一个没有上下文、没有走任何生命周期流程的普通Java对象,和屏幕上正在显示、弹出BottomSheetDialog的那个真实MainActivity实例没有任何关联。你给这个自己new出来的无效对象设置回调,真实运行的MainActivity里的接口实例自然始终是null,调用时直接空指针。 - 你用的接口回调方案本身就不适用跨独立Activity的通信场景。接口回调仅适合同一上下文内的通信(比如Activity和它内部弹出的Dialog、挂载的Fragment之间传值),两个独立启动的Activity之间你无法稳定持有对方的有效实例引用,强行用回调传值不仅拿不到正确实例,还很容易引发内存泄漏。
可落地的解决方案
结合你的业务场景(MainActivity填写百分比配置,传递给ProductInformationActivity使用),选择标准实现方案即可:
方案1:Intent传参(最匹配当前场景,实现最简单)
如果是从MainActivity填完参数后跳转到ProductInformationActivity,直接用Intent携带参数传递即可,删掉你写的所有自定义回调相关代码:
- 先修改Percentage模型类,实现
Parcelable接口(Android Studio可通过插件自动生成Parcelable实现代码,性能比Serializable更好)。 - 修改MainActivity中保存按钮的点击逻辑,校验输入合法后构造Percentage实例,直接通过Intent启动目标页面并传值:
// 保存按钮点击事件内的逻辑 if (/* 三个输入框非空校验通过 */) { Percentage percentage = new Percentage(); // 给percentage的三个百分比字段赋值 Intent intent = new Intent(MainActivity.this, ProductInformationActivity.class); intent.putExtra("extra_percentage", percentage); startActivity(intent); // 关闭弹窗、弹出保存成功提示 bottomSheetDialog.dismiss(); Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "请填写所有字段", Toast.LENGTH_SHORT).show(); }
- 在ProductInformationActivity的
onCreate生命周期方法中,直接从Intent取出传递过来的实例,用来更新页面UI即可:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_product_information); Percentage percentage = getIntent().getParcelableExtra("extra_percentage"); if (percentage != null) { // 取percentage中的三个百分比数值,更新对应带百分比的价格文本 } }
方案2:共享数据层(适合多页面反复读写配置的场景)
如果ProductInformationActivity修改百分比后还要回传给MainActivity,或者多个页面都需要复用这套配置,可以把Percentage数据存在共享ViewModel、本地轻量存储(SharedPreferences/Mmkv)这类公共数据层,所有页面都从公共数据层读写数据即可,不要在页面之间互相持有实例引用。
注意:禁止把Activity、Context这类组件对象存入静态变量、单例类,会引发严重的内存泄漏甚至崩溃。
避坑提醒
- 任何场景下都不要手动new Activity/Service/Fragment这类系统托管组件,这类组件的实例创建、生命周期调度全由系统控制,手动new出的实例没有运行上下文,完全无法正常工作。
- 跨组件通信要选对应场景的标准方案:同页面内和子组件(Dialog、Fragment)通信用接口回调/页面级ViewModel;启动新页面单向传值用Intent;页面返回传值用Activity Result API;全局多页面共享数据用共享ViewModel/本地存储。
内容的提问来源于stack exchange,提问作者mehdi shadrooh
相关产品推荐
相关产品推荐

