1

フラグメント ビューが適切に更新されないという奇妙な問題が発生していますが、アプリを閉じてしばらくしてから再度開いた後にのみ発生します。

TabSwitcherActivity含む がありViewPagerます。はViewPager3 つのフラグメントを切り替え、各フラグメントは同じ情報の異なるビューを表します。情報が古くなる特定のイベントが発生する可能性があるため、フラグメントに通知してビューを更新する必要があります。これを実現するために、3 つのフラグメントを反復処理して更新するように指示するTabSwitcherActivityメソッドが呼び出されます。notifyDataSetChanged()これが(私が思うに)最も関連性の高いコードです:

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アレイに正しく格納されていないことがわかりました。

4

2 に答える 2

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();
    }
}

これは私の新しい実装で、不正なフラグメント参照を保持する配列によって引き起こされる問題を取り除きます:

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古いフラグメントを my クラスに更新させる方法です。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();
    }
}
于 2013-07-18T02:55:26.717 に答える