Parcelable传递数据致原ArrayList被修改的问题求助
问题原因与解决方案
你碰到的这个问题其实是Java里引用类型的特性导致的——ArrayList属于对象类型,赋值和传递的时候都是传的内存引用,而不是整个列表的拷贝。也就是说,你原Fragment里的skillsLit、Skills对象里的skills、还有第二个Fragment Adapter里的skills,其实都是指向同一个内存里的列表。所以你在Adapter里删除元素时,原Fragment的列表自然也会跟着被修改。
解决思路
核心就是让传递的列表成为原列表的副本,而不是直接传递引用。下面是具体的修改方案:
1. 修改Skills类,确保存储的是列表副本
可以在setSkills方法里直接创建新的ArrayList来存储传入的列表,这样无论外部怎么传,Skills里的列表都是独立的副本:
public class Skills implements Parcelable { private ArrayList<String> skills; public ArrayList<String> getVacancySkills() { return skills; } public void setSkills(ArrayList<String> skills) { // 创建新的ArrayList,复制传入的列表元素,避免引用传递 this.skills = new ArrayList<>(skills); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeStringList(this.skills); } public Skills() { } protected Skills(Parcel in) { // 同样,在这里创建新的ArrayList,确保从Parcel读取的也是副本 this.skills = new ArrayList<>(in.createStringArrayList()); } public static final Parcelable.Creator<Skills> CREATOR = new Parcelable.Creator<Skills>() { @Override public Skills createFromParcel(Parcel source) { return new Skills(source); } @Override public Skills[] newArray(int size) { return new Skills[size]; } }; }
2. (可选)传递数据时主动传入副本
如果不想修改Skills类,也可以在传递数据的时候,直接传入原列表的副本:
@OnClick(R.id.card_add_skill) public void showAddSkills() { Bundle data = new Bundle(); Skills skills = new Skills(); // 传入原列表的副本,而不是原列表本身 skills.setSkills(new ArrayList<>(skillsLit)); data.putParcelable(ExtraKeys.VACANCY_SKILLS, skills); VacancyEditSkillsFragment vacancyEditSkillsFragment = new VacancyEditSkillsFragment(); FragmentUtils.addFragment( getActivity().getSupportFragmentManager(), vacancyEditSkillsFragment , true, App.getContext().getString(R.string.skills), data ); }
3. 确认Adapter操作的是副本
经过上面的修改,第二个Fragment里mSkills.getVacancySkills()拿到的已经是独立的副本了,Adapter里删除元素只会修改这个副本,不会影响原Fragment的skillsLit。
这样修改之后,你在RecyclerView里删除技能项,返回原Fragment时,原列表就不会被改动了。
内容的提问来源于stack exchange,提问作者Ahmad Nasser
相关产品推荐
相关产品推荐

