2012-06-21 85 views
3

我有这样的结构:在活动和片段之间传递数据或行为

活动A有一个ViewPager。 ViewPager的页面是已知片段。

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

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

所以我要通过这个列表

A - >片段(S) - “乙

首先,我发现这是不可能使用片段的构造函数将数据传递给它。我必须使用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代码(写入/读取)是疼痛。也许我只是坚持静态数据...

+0

我得到了同样的问题。我的复杂数据使用片段计算并显示在活动A的列表中,但细节将显示在任一活动B中使用片段或两个窗格布局中的同一活动中,但具有不同的详细信息片段。我完全不知道,但是可以将我的详细数据加以分类,这是一种痛苦...你有没有想出更好的想法?例如把它作为中间介质放在应用程序对象中? – Zordid

回答

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,然后像Bundle.putParcelableArray()一样将它添加到你的Fragment参数中。

+0

感谢您的回答。在每个片段中,我正在显示一个网格,并且想要传递网格的模型项目列表。我尝试了Parcelable,但实现很糟糕(我的数据类型有很多字段,也有类型映射等等,编写代码来序列化和反序列化是一个真正的痛苦)。而且它也很慢,我的屏幕一会儿空白。所以我想我必须使用静态数据。 – Ixx

+0

呃,对不起,屏幕是空白的,因为别的东西,而不是可parcelable。 – Ixx

+1

我想,假设你确定了你的条件,你可以通过演员获得onAttach中的信息:@Override public void onAttach(Activity activity){ mFragmentList =((MyActivity)activity).getList(); }' – Makario