在片段与调用值之间传递数据而不是引用

时间:2016-11-18 13:29:21

标签: java android android-fragments parcelable

我正在尝试将MyData(Parcelable对象包括ArrayList)从AFragment传递给BFragment。 当然,它可行。但是,ArrayList的引用是相同的。

我查看了有关Parcelable的各种文章,最后我发现Parcelable仅在两个对象处于不同任务时重新创建实例。

如何传递基本类型而不是引用类型的数据?

我写了如下代码。

迈德特

public class MyData implements Parcelable {

public List<String> mList = new ArrayList<>(0);

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel out, int flags) {
    out.writeStringList(mList);
}

public static final Parcelable.Creator<MyData> CREATOR = new Parcelable.Creator<MyData>() {
    public MyData createFromParcel(Parcel in) {
        return new MyData(in);
    }

    public MyData[] newArray(int size) {
        return new MyData[size];
    }
};

private MyData(Parcel in) {
    in.writeStringList(mList);
}

public MyData() {
}
}

MainActivity

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    SampleFragment sampleFragment = new SampleFragment();
    replaceFragment(sampleFragment);
}

public void replaceFragment(Fragment fragment) {
    FragmentManager manager = getSupportFragmentManager();

    if (manager.findFragmentByTag(fragment.getClass().getCanonicalName()) != null) {
        return;
    }
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.replace(R.id.container_layout, fragment, fragment.getClass().getCanonicalName());
    transaction.addToBackStack(null);
    transaction.commit();
}
}

AFragment

public class SampleFragment extends Fragment implements View.OnClickListener {

MainActivity mActivity;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mActivity = (MainActivity) context;
}

@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Nullable
@Override
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.sample1, container, false);
    view.findViewById(R.id.button).setOnClickListener(this);
    return view;
}

@Override
public void onClick(View v) {
    int id = v.getId();
    if (id == R.id.button) {
        List<String> list = new ArrayList<>(0);
        list.add("sample1");
        list.add("sample2");
        list.add("sample3");
        HogeData data = new HogeData();
        data.mList = list;
        SampleFragment2 sampleFragment2 = new SampleFragment2();
        Bundle bundle = new Bundle();
        bundle.putParcelable(sampleFragment2.getClass().getCanonicalName(), data);
        sampleFragment2.setArguments(bundle);
        mActivity.replaceFragment(sampleFragment2);
    }
}
}

BFragment

public class SampleFragment2 extends Fragment {

MainActivity mActivity;
HogeData mData;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mActivity = (MainActivity) context;
}

@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Bundle bundle = getArguments();
    mData = bundle.getParcelable(getClass().getCanonicalName());
}

@Nullable
@Override
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
    return inflater.inflate(R.layout.sample2, container, false);
}

问题是当我将数据(MyData)从AFragment传递给BFragment时,arraylist(mList)的引用是相同的。这会导致我在BFragment中更改mList的值时,AFragment中的mList值也会发生变化。 我不知道解决这个问题。

2 个答案:

答案 0 :(得分:2)

来自Google Developers网站:

  

通常你会想要一个片段与另一个片段进行通信   示例根据用户事件更改内容。所有   片段到片段的通信是通过相关联的   活动。两个碎片永远不应该直接沟通。

一个好的做法是通过接口将数据发送到Activity。活动将接收数据,并且应该能够通过方法将数据发送到第二个片段。

请阅读thisthis

答案 1 :(得分:0)

Fragment fragmentGet1 = new FragmentGet1();
Fragment fragmentGet2 = new FragmentGet2();
Fragment fragmentGet2 = new FragmentGet3();

fragmentGet1.setArguments(bundle);
fragmentGet2.setArguments(bundle);
fragmentGet3.setArguments(bundle);

您可以创建所有3个片段的实例,但只能使用FragmentGet1的实例。其他的不使用。之后,当您创建任何这些片段的另一个实例时,它将没有args,因为它是一个完全独立的对象。

您需要的是每次创建新片段时都向前传递包。如果你想在已经创建的片段中创建它,它看起来会像这样:

public void showNextFragment() {

    FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

    Fragment fragmentGet2 = new FragmentGet2();

    if(this.getArguments() != null)
        fragmentGet2.setArguments(this.getArguments());

    fragmentTransaction.replace(R.id.frame_container, fragmentGet2);
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();

}

示例

要将Student对象传递给Activity,只需执行以下操作:

Student s = //get it here
Bundle b = new Bundle();
b.putParcelable("student", s);

Intent i = new Intent(getActivity(), ThatOtherActivity.class);
i.putExtra("extraWithStudent", b);
startActivity(i);

然后阅读活动中的数据:

Intent incomingIntent = getIntent();
Bundle b = incomingIntent.getBundleExtra("extraWithStudent");
Student s = (Student) b.getParcelable("student");
s