2

ListFragments をページングする ViewPager があります。各ページは特定の日付であり、各ページのリストには複数のカテゴリのアイテムが含まれています。

ユーザーは、ダイアログを介して表示されるカテゴリをいつでも切り替えることができます。カテゴリ リストの変更後にインスタンス化されたページ (およびそのフラグメント) では、新しい設定でインスタンス化されるため (変更時に FragmentStatePagerAdapter に渡される)、これは問題ではありません。

But my problem is with all pages that have already been instantiated up to when the user changes the categories list. These pages (or rather, their fragments) need to immediately refresh. To accomplish this I need to be able to call a method (changeData()) to pass the new categories settings to each ListFragment which then calls notifyDataSetChanged() so they will refresh their view.

How can I perform this call on already-instantiated fragments in the FragmentStatePagerAdapter?

Here is my code for the FragmentStatePagerAdapter and the ListFragments used to populate the pages:

public static class ListingPagerAdapter extends FragmentStatePagerAdapter {

    private Date mStartingDate;
    private String mListingCat;
    private Calendar cal;

    public ListingPagerAdapter(FragmentManager fm, Date startDate, String listingCat) {
        super(fm);
        mStartingDate = startDate;
        mListingCat = listingCat;
        cal = Calendar.getInstance();
    }

    public void setListingCategories(String categories) {
        mListingCat = categories;
        //notifyDataSetChanged();
    }

    @Override
    public Fragment getItem(int i) {
        cal.setTime(mStartingDate);
        cal.add(Calendar.DAY_OF_YEAR,i);
        Bundle fragmentArgs = new Bundle();
        fragmentArgs.putString(Utils.DIRECTORY_CAT_STORE_KEY, mListingCat);
        fragmentArgs.putLong(Utils.FILTER_DATE_STORAGE_KEY, cal.getTimeInMillis());
        ListingFragment listingFragment = ListingFragment.newInstance(fragmentArgs);
        return listingFragment;
    }

    @Override
    public int getItemPosition(Object object) {
        if (object instanceof ListingFragment) {
            ((ListingFragment) object).changeData(mListingCat, 0);
        }
        return super.getItemPosition(object);
    }

    @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }
}

上記の seListingCategories() メソッドを使用してアダプターにカテゴリ文字列を設定しているため、新しくインスタンス化されたすべてのフラグメントに正しいカテゴリが表示されます。同じメソッドで、Adapter で notifyDataSetChanged() を呼び出す行がコメント アウトされていることに気付くでしょう。

その呼び出しにより、アダプタはメモリ内のすべての Fragment (現在のページとまだ破棄されていない他のすべてのページ) に対して getItemPosition() を呼び出します。そして、ビューは正常に更新されました。

ただし、(保存された状態で) 既に破棄されたフラグメントは、更新されたカテゴリ リストを持たない保存された状態に復元されるようです。言うまでもなく、これはやり過ぎのようです。既存のオブジェクトを更新するだけでよいのに、なぜすべてのフラグメントを破棄して再作成するのでしょうか?

とにかく、以下は FragmentStatePageAdapter で使用される ListFragment クラスです。

public static class ListingFragment extends ListFragment {

    private Map<String,String> filters;
    private JSONArray mListingData;

    public static ListingFragment newInstance(Bundle args) {
        ListingFragment lf = new ListingFragment();
        lf.setArguments(args);
        return lf;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        if (filters == null)
            filters = new HashMap<String, String>();

        if (savedInstanceState != null) {
            filters.put(Utils.DIRECTORY_CAT_STORE_KEY, savedInstanceState.getString(Utils.DIRECTORY_CAT_STORE_KEY));
            filters.put(Utils.FILTER_DATE_STORAGE_KEY, ""+savedInstanceState.getLong(Utils.FILTER_DATE_STORAGE_KEY));
        }
        else {
            filters.put(Utils.DIRECTORY_CAT_STORE_KEY, getArguments().getString(Utils.DIRECTORY_CAT_STORE_KEY));
            filters.put(Utils.FILTER_DATE_STORAGE_KEY, ""+getArguments().getLong(Utils.FILTER_DATE_STORAGE_KEY));
        }

        mListingData = Utils.getDataByTypeAndFilters(getResources().getString(R.string.nav_promotions), filters, getActivity().getResources());
        setListAdapter(new PromotionListingAdapter(getActivity(), mListingData));

    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putString(Utils.DIRECTORY_CAT_STORE_KEY, filters.get(Utils.DIRECTORY_CAT_STORE_KEY));
        outState.putLong(Utils.FILTER_DATE_STORAGE_KEY, Long.parseLong(filters.get(Utils.FILTER_DATE_STORAGE_KEY)));
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onListItemClick(ListView l, View view, int position, long id) {
        Intent newDetailIntent = new Intent(getActivity(), PromotionDetails.class);
        newDetailIntent.putExtra(Utils.LISTING_OBJECT_STORE_KEY, ((JSONObject) l.getAdapter().getItem(position)).toString());
        startActivity(newDetailIntent);
    }

    public void changeData(String category, long date) {
        if (category != null)
            filters.put(Utils.DIRECTORY_CAT_STORE_KEY, category);
        if (date > 0)
            filters.put(Utils.FILTER_DATE_STORAGE_KEY, ""+date);
        mListingData = Utils.getDataByTypeAndFilters(getResources().getString(R.string.nav_promotions), filters, getActivity().getResources());
        PromotionListingAdapter promotionsAdapter = ((PromotionListingAdapter) getListAdapter());
        promotionsAdapter.setData(mListingData);
        promotionsAdapter.notifyDataSetChanged();
    }
}

助けてくれてありがとう!

4

0 に答える 0