在活动和片段之间传递数据或行为

时间:2012-06-21 08:20:59

标签: android android-activity fragment

我有这个结构:

活动A有一个ViewPager。 ViewPager的页面就像已知的碎片一样。

活动A有一个复杂对象列表,我想在页面中显示。

当用户点击ViewPager活动中的项目时,必须启动B。活动B还需要具有复杂对象的列表。

所以我必须传递这个清单

A - >片段 - >乙

首先我发现不可能使用片段的构造函数将数据传递给它。我必须使用parcelable或serializable。在片段中,我必须再次包裹或序列化以传递给B.

但我不想将整个复杂数据列表序列化或包裹2次,只能将其传递给B.

我想避免使用静态字段。

然后我想到将一个监听器传递给片段,该片段监听项目点击,并通知我的活动A和活动A然后用数据启动活动B.这对我来说看起来最干净,因为A实际上是数据所属的那个,所以A用数据开始片段,片段返回A然后A用数据开始B.我不必在任何地方传递数据(序列化!)。

但这似乎不起作用,因为如何使用序列化将侦听器传递给片段?在片段中使用侦听器返回活动有什么问题?

我该如何解决这个问题?

修改

我在一个关于对话框片段的帖子中找到了这个解决方案:Get data back from a fragment dialog - best practices?

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
    mListener = (OnArticleSelectedListener) activity;
} catch (ClassCastException e) {
    throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
}
}

所以我将它添加到我的片段中,让我的活动实现某个界面。

这将解决将数据从片段传递到B的问题。但是我仍然需要将列表从A传递给片段。可能我必须使用Parcelable ......

修改:我尝试过 Parcelable ,但是有效。但是,我列表中的对象在它们之间也有很多字段,例如。编写Parcelable代码(写/读)是痛苦。也许我只是坚持静态数据......

1 个答案:

答案 0 :(得分:2)

您找到的侦听器解决方案非常出色,实际上是Google推荐的(http://developer.android.com/training/basics/fragments/communicating.html)。

至于将数据传递给片段的剩余问题,您确定需要传递整个列表,而不仅仅是ViewPager中每个片段的列表元素吗?如果你只需要一个元素,你可以这样做:

    /*
     * An adapter for swiping through the fragments we have.
     */
    private class CustomPagerAdapter extends FragmentStatePagerAdapter {

        List<Thing> things;

        public CustomPagerAdapter(FragmentManager fragmentManager, List<Thing> things) {
            super(fragmentManager);
            this.things = things;
        }

        @Override
        public int getCount() {
            return things.size();
        }

        @Override
        public Fragment getItem(int position) {
            return ThingFragment.newInstance(things.get(position));
        }
    }

    /*
     * Loads a view based on the thing.
     */
    private static class ThingFragment extends Fragment {

        private String name;

        static ThingFragment newInstance(Thing thing) {

            ThingFragment f = new ThingFragment();

            // add some arguments to our fragment for onCreateView
            Bundle args = new Bundle();
            args.putString("name", thing.getName());
            f.setArguments(args);

            return f;
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            name = getArguments().getString("name");
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

            View v = inflater.inflate(R.layout.thing_fragment_layout, container, false);
                    TextView t = (TextView)v.findViewById(R.id.thingText);
            t.setText(name);
            return v;
        }
    }

并将您的列表传递给适配器。当然,这需要动态创建动态,但是膨胀xml片段非常容易。

如果你确实需要传递整个列表,是的,你可能必须使单个复杂对象Parcelable,然后将它添加到你的Fragment args,就像Bundle.putParcelableArray()一样。