Android Fragments 作为数组存储在 FragmentPagerAdapter 中,离开并返回应用程序后未刷新

mka*_*erg 1 android fragment fragmentpageradapter

我有一个奇怪的问题,即片段视图无法正确刷新,但只有在应用程序关闭并在一段时间后重新打开后才会发生。

我有一个TabSwitcherActivity包含ViewPager. 的ViewPager3个片段之间切换,并且每个片段表示相同的信息的不同视图。可能会发生某些事件,这会导致信息变得陈旧,因此需要通知片段以刷新视图。为此,我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();
        }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,这在第一次启动应用程序时按预期工作。问题是在应用程序关闭并在一段时间后重新打开后,TabSwitcherActivity.notifyDataSetChanged()在应用程序运行时调用不会更新片段视图(这适用于应用程序在重新启动后第一次启动时)。这让我相信我没有正确处理碎片存在生命周期情况。知道这可能是什么吗?我突然想到,如果这些片段被销毁并重新创建,它们可能没有正确存储在我的mFragments数组中。

mka*_*erg 5

我正在回答我自己的问题,以防其他人遇到与我类似的问题。我能够根据 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的新实现,它消除了由保存错误片段引用的数组引起的问题:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,唯一剩下的问题是如何让我的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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,剩下的就是让片段自行注册以进行更新:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)