如何跨Activity访问MainActivity的ArrayList存储Recipe对象
跨Activity回传Recipe对象写入集合的正确实现
Android中两个Activity由系统独立管理生命周期,绝对不要直接在createRecipe页面持有MainActivity的引用访问内部集合,这种写法会触发内存泄漏、空指针崩溃等问题。正确逻辑是:createRecipe仅负责收集用户输入生成Recipe实例,通过页面结果回调把实例传回MainActivity,由MainActivity自行完成集合添加操作。
实现步骤
- 第一步:让Recipe实体类支持序列化,满足Intent跨页面传递自定义对象的要求
import java.io.Serializable; public class Recipe implements Serializable { // 按自身业务定义类属性,示例如下 private String recipeName; private int duration; private String ingredients; private String description; private String steps; // 补全构造方法、getter/setter public Recipe(String recipeName, int duration, String ingredients, String description, String steps) { this.recipeName = recipeName; this.duration = duration; this.ingredients = ingredients; this.description = description; this.steps = steps; } // 自行补全get/set方法 }
如果追求更高的跨页传输性能,可以实现Parcelable接口,用Android Studio的Parcelable生成插件可以一键生成实现代码,后续传值逻辑和Serializable一致,仅取数据时把getSerializableExtra换成getParcelableExtra即可。
- 第二步:在MainActivity中注册页面结果回调,替换原有的跳转逻辑
首先在MainActivity的成员位置定义结果启动器,同时记得提前初始化recipeList:
// MainActivity成员变量 ArrayList<Recipe> recipeList; // 注册创建菜谱页的结果回调 private final ActivityResultLauncher<Intent> createRecipeLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == RESULT_OK && result.getData() != null) { // 取出回传的新菜谱对象 Recipe newRecipe = (Recipe) result.getData().getSerializableExtra("new_recipe"); // 直接写入当前页面的集合即可 recipeList.add(newRecipe); // 如果页面绑定了列表适配器,记得通知刷新 // recipeAdapter.notifyDataSetChanged(); } } ); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 必须先初始化集合,避免空指针 recipeList = new ArrayList<>(); // 原来跳转到createRecipe的代码替换成下面的写法 findViewById(R.id.to_create_recipe_btn).setOnClickListener(v -> { Intent intent = new Intent(MainActivity.this, createRecipe.class); createRecipeLauncher.launch(intent); }); }
- 第三步:修改createRecipe页的提交逻辑,完成对象创建后回传再关闭页面
找到代码中标注// How should I save it的位置,替换成如下逻辑:
// 拿到创建好的Recipe实例(确保你的CreateRecipe方法有返回值,返回生成的Recipe对象) Recipe newRecipe = CreateRecipe(etRecipeName, etDuration, etIngredient, etDesc, etSteps); Toast.makeText(createRecipe.this, "Recipe Created", Toast.LENGTH_SHORT).show(); // 封装回传数据 Intent resultIntent = new Intent(); resultIntent.putExtra("new_recipe", newRecipe); setResult(RESULT_OK, resultIntent); // 关闭当前页回到MainActivity finish();
禁止写法提醒
不要把recipeList改成public static公共静态变量让createRecipe直接操作:
- 静态变量的生命周期和应用进程绑定,会持有Activity引用造成内存泄漏
- 应用在后台内存不足时,静态变量会被系统回收,切回前台会直接触发空指针崩溃
- 代码耦合度极高,后续维护非常容易出问题
内容的提问来源于stack exchange,提问作者Kelven Lim
相关产品推荐
相关产品推荐

