1. ホーム
  2. android

[解決済み] ViewPagerの一部であるListFragmentのデータを更新する

2022-05-15 16:14:06

質問

Androidでv4互換のViewPagerを使用しています。 FragmentActivityにはたくさんのデータがあり、ViewPagerの異なるページで異なる方法で表示されます。 今のところ、同じListFragmentのインスタンスを3つ持っているだけですが、将来的には異なるListFragmentのインスタンスを3つ持つ予定です。 ViewPagerは縦長の携帯電話の画面にあり、リストは横並びではありません。

ListFragmentのボタンを押すと、(FragmentActivityを介して)別のフルページアクティビティが起動し、FragmentActivityがデータを変更し、保存し、ViewPagerのすべてのビューを更新しようとします。 ここで、私は行き詰っています。

public class ProgressMainActivity extends FragmentActivity
{
    MyAdapter mAdapter;
    ViewPager mPager;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
    ...
        mAdapter = new MyAdapter(getSupportFragmentManager());

        mPager = (ViewPager) findViewById(R.id.viewpager);
        mPager.setAdapter(mAdapter);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        ...
        updateFragments();
        ...
    }
    public void updateFragments()
    {
        //Attempt 1:
        //mAdapter.notifyDataSetChanged();
        //mPager.setAdapter(mAdapter);

        //Attempt 2:
        //HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentById(mAdapter.fragId[0]);
        //fragment.updateDisplay();
    }

    public static class MyAdapter extends FragmentPagerAdapter implements
         TitleProvider
    {
      int[] fragId = {0,0,0,0,0};
      public MyAdapter(FragmentManager fm)
      {
         super(fm);
      }
      @Override
      public String getTitle(int position){
         return titles[position];
      }
      @Override
      public int getCount(){
         return titles.length;
      }

      @Override
      public Fragment getItem(int position)
      {

         Fragment frag = HomeListFragment.newInstance(position);
         //Attempt 2:
         //fragId[position] = frag.getId();
         return frag;
      }

      @Override
      public int getItemPosition(Object object) {
         return POSITION_NONE; //To make notifyDataSetChanged() do something
     }
   }

    public class HomeListFragment extends ListFragment
    {
    ...
        public static HomeListFragment newInstance(int num)
        {
            HomeListFragment f = new HomeListFragment();
            ...
            return f;
        }
   ...

さて、ご覧の通り、最初の試みはFragmentPagerAdapter全体に対してnotifyDataSetChangedを行うことでした。これは時々データを更新することを示していましたが、他の場合はIllegalStateExceptionが発生しました。Can't perform this action after onSaveInstanceState.

2回目の試みは、ListFragmentの更新関数を呼び出そうとしたのですが、getItemのgetIdが0を返しました。 ドキュメントにあるように、私は以下の方法で試しました。

FragmentManagerからFragmentへの参照を取得する。 findFragmentById()またはfindFragmentByTag()を使用して、FragmentManagerからフラグメントの参照を取得します。

しかし、フラグメントのタグやIDを知らないのです。ViewPagerにはandroid:id"@+id/viewpager"、ListFragmentレイアウトのListViewにはandroid:id"@android:id/list"がありますが、これは役に立ちそうにないですね。

そこで、どのようにすればよいでしょうか。 a) 一度に安全にViewPager全体を更新する (理想的には、ユーザーを以前いたページに戻す) - ユーザーがビューの変更を見ることは問題ないです。 あるいは、できれば b) 影響を受ける各ListFragmentで関数を呼び出して、ListViewを手動で更新します。

どんな助けでもありがたく受け取ります!

どのように解決するのですか?

Fragementがインスタンス化されるたびに、タグを記録するようにしてください。

public class MPagerAdapter extends FragmentPagerAdapter {
    private Map<Integer, String> mFragmentTags;
    private FragmentManager mFragmentManager;

    public MPagerAdapter(FragmentManager fm) {
        super(fm);
        mFragmentManager = fm;
        mFragmentTags = new HashMap<Integer, String>();
    }

    @Override
    public int getCount() {
        return 10;
    }

    @Override
    public Fragment getItem(int position) {
        return Fragment.instantiate(mContext, AFragment.class.getName(), null);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object obj = super.instantiateItem(container, position);
        if (obj instanceof Fragment) {
            // record the fragment tag here.
            Fragment f = (Fragment) obj;
            String tag = f.getTag();
            mFragmentTags.put(position, tag);
        }
        return obj;
    }

    public Fragment getFragment(int position) {
        String tag = mFragmentTags.get(position);
        if (tag == null)
            return null;
        return mFragmentManager.findFragmentByTag(tag);
    }
}