【问题标题】:Passing data or behaviour between activities and fragments在活动和片段之间传递数据或行为
【发布时间】:2012-06-21 08:20:59
【问题描述】:

我有这个结构:

Activity A 有一个 ViewPager。 ViewPager 的页面称为 Fragment。

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

当用户单击 ViewPager 活动 B 内的项目时,必须启动。 Activity B 也需要包含复杂对象的列表。

所以我必须通过这个列表

A -> 片段 -> B

首先我发现无法使用片段的构造函数向其传递数据。我必须使用可打包或可序列化的。在片段中,我必须再次打包或序列化以传递给 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 代码(写/读)是一种痛苦。也许我只是坚持静态数据...

【问题讨论】:

  • 我遇到了同样的问题。我的复杂数据是使用片段计算并显示在活动 A 中的列表中,但详细信息将使用片段显示在活动 B 中,或者在同一活动中的两个窗格布局中显示,但细节片段不同。我完全不知道,只能打包我的详细数据,这很痛苦……你有没有更好的想法?例如将其作为中间媒介放在应用程序对象中?

标签: android android-activity fragment


【解决方案1】:

您发现的侦听器解决方案非常出色,实际上是 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()。

【讨论】:

  • 感谢您的回答。在每个片段中,我都显示了一个网格,并且我想传递网格的模型项列表。我尝试了 Parcelable 但实现很糟糕(我的数据类型有很多字段,还有类型 map 等等,编写代码来序列化和反序列化真的很痛苦)。而且它也很慢,我的屏幕有一段时间是空白的。所以我想我将不得不使用静态数据。
  • 呃,抱歉,屏幕是空白的,因为别的东西,不是 parcelable。
  • 我想,假设你确定你的条件,你可以通过演员获得 onAttach 中的信息:@Override public void onAttach(Activity activity) { super.onAttach(activity); mFragmentList = ((MyActivity)activity).getList(); }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
  • 2013-12-27
  • 2014-04-03
  • 1970-01-01
  • 2013-06-21
相关资源
最近更新 更多