我遇到一个奇怪的问题,片段视图无法正常刷新,但只有在应用关闭并在一段时间后重新打开后才会发生。
我有TabSwitcherActivity
,其中包含ViewPager
。 ViewPager
在3个片段之间切换,每个片段代表相同信息的不同视图。某些事件可能会导致信息变得陈旧,因此需要通知片段以刷新视图。为实现此目的,我的TabSwitcherActivity
有一个名为notifyDataSetChanged()
的方法,它将迭代3个片段并告诉它们刷新。这是(我认为)最相关的代码:
public class TabSwitcherActivity extends FragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Used to keep track of the child fragments of this activity so we can update their list adapters.
mFragments = new ArrayList<Fragment>();
// Set up the view pager and tab adapter.
setContentView(R.layout.pager_layout);
mViewPager = (ViewPager) super.findViewById(R.id.pager);
mFragments.add(Fragment.instantiate(this, FragmentOne.class.getName()));
mFragments.add(Fragment.instantiate(this, FragmentTwo.class.getName()));
mFragments.add(Fragment.instantiate(this, FragmentThree.class.getName()));
mViewPager.setAdapter(new ListPagerAdapter(super.getSupportFragmentManager(), mFragments));
}
public void notifyDataSetChanged() {
for (Fragment fragment : mFragments) {
if (fragment instanceof IDataSetChangedListener) {
((IDataSetChangedListener) fragment).notifyDataSetChanged();
}
}
}
}
现在,这是第一次启动应用程序时的预期效果。问题是应用程序关闭并在一段时间后重新打开后,在应用程序运行时调用TabSwitcherActivity.notifyDataSetChanged()
不会更新片段视图(这在重新启动后第一次启动应用程序时有效)。这让我相信存在一个生命周期情况,我正在处理不正确的碎片。知道这可能是什么吗?我发现如果片段被破坏并重新创建,它们可能没有正确存储在我的mFragments
数组中。
答案 0 :(得分:3)
我正在回答我自己的问题,以防其他人遇到类似的问题。我能够根据invertigo的评论解决问题。我将发布一些代码重要部分的一般化部分。
正如我所怀疑的那样,如果应用程序销毁并重新创建了存储在数组中的片段,则这些片段未正确更新。 (当应用程序关闭并重新打开时,有时会发生这种情况。)因为我在FragmentPagerAdapter
实现中使用它来存储我的选项卡的片段,所以删除数组有点棘手。
这是我的旧ListPagerAdapter
课程:
public class ListPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragments;
public ListPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public String getPageTitle(int position) {
return ((ITitledFragment) mFragments.get(position)).getTitle();
}
}
这是我的新实现,它消除了由持有错误片段引用的数组引起的问题:
public class ListPagerAdapter extends FragmentPagerAdapter {
private static final int FRAGMENT_ONE_POSITION = 0;
private static final int FRAGMENT_TWO_POSITION = 1;
private static final int FRAGMENT_THREE_POSITION = 2;
private static final int COUNT = 3;
public ListPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case FRAGMENT_ONE_POSITION:
return new FragmentOne();
case FRAGMENT_TWO_POSITION:
return new FragmentTwo();
case FRAGMENT_THREE_POSITION:
return new FragmentThree();
}
return null;
}
@Override
public int getCount() {
return COUNT;
}
@Override
public String getPageTitle(int position) {
switch (position) {
case 0:
return FragmentOne.getTitle();
case 1:
return FragmentTwo.getTitle();
case 2:
return FragmentThree.getTitle();
}
return null;
}
}
然后,唯一剩下的问题是如何让我的TabSwitcherActivity
类在陈旧时更新所有片段。正如invertigo所指出的,这可以用标签来完成。但是,我决定使用一种方法,其中每个片段在创建时将自身注册到活动,并在销毁之前取消注册。活动可以迭代已注册的片段以更新它们。
来自TabSwitcherActivity
的相关代码:
class TabSwitcherActivity extends FragmentActivity {
private List<Fragment> mFragments;
private void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Used to keep track of the child fragments of this activity so we can update their list adapters.
mFragments = new ArrayList<Fragment>();
// Set up the view pager and tab adapter.
setContentView(R.layout.pager_layout);
mViewPager = (ViewPager) super.findViewById(R.id.pager);
mViewPager.setAdapter(new ListPagerAdapter(super.getSupportFragmentManager()));
}
public void startTrackingFragment(Fragment f) {
mFragments.add(f);
}
public void stopTrackingFragment(Fragment f) {
mFragments.remove(f);
}
public void notifyDataSetChanged() {
for (Fragment fragment : mFragments) {
if (fragment instanceof IDataSetChangedListener) {
((IDataSetChangedListener) fragment).notifyDataSetChanged();
}
}
}
}
有了这个,剩下的就是让片段自己注册更新:
public class FragmentOne extends Fragment implements IDataSetChangedListener {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((TabSwitcherActivity) getActivity()).startTrackingFragment(this);
}
public void onDestroy() {
((TabSwitcherActivity) getActivity()).stopTrackingFragment(this);
super.onDestroy();
}
}
答案 1 :(得分:1)
您可以随时刷新片段的onResume()中的数据,或者在活动的onResume()中调用notifyDataSetChanged()。
re:“我发现如果碎片被破坏并重新创建,它们可能无法正确存储在我的mFragments数组中。” 不是将片段存储在数组中,而是使用片段管理器按标签或id获取片段。
http://developer.android.com/guide/components/fragments.html#Managing