我有这个结构:
活动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代码(写/读)是痛苦。也许我只是坚持静态数据......
答案 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()一样。