首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >作为ViewPager的一部分更新ListFragment中的数据

作为ViewPager的一部分更新ListFragment中的数据
EN

Stack Overflow用户
提问于 2011-09-11 23:17:08
回答 10查看 73K关注 0票数 142

我使用的是安卓系统中的v4兼容性ViewPager。我的FragmentActivity有一堆数据,它们将在我的ViewPager的不同页面上以不同的方式显示。到目前为止,我只有3个相同ListFragment的实例,但将来我会有3个不同ListFragments的实例。ViewPager在垂直的手机屏幕上,列表不是并排的。

现在,ListFragment上的一个按钮启动一个单独的整页活动(通过FragmentActivity),该活动返回数据,FragmentActivity修改数据,保存数据,然后尝试更新其ViewPager中的所有视图。它就在这里,我被困在这里。

代码语言:javascript
复制
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 this action on onSaveInstanceState。

我第二次尝试调用ListFragment中的更新函数,但getItem中的getId返回0。根据我尝试过的文档

使用findFragmentById()或findFragmentByTag()从FragmentManager获取对片段的引用

但我不知道我的片段的标签或id!我为ViewPager设置了一个android:id="@+id/viewpager“,在ListFragment布局中为我的ListView设置了一个android:id="@android:id/list”,但我不认为这些有用。

那么,我该如何: a)一次性安全地更新整个ViewPager (理想情况下,将用户返回到他之前所在的页面)-用户看到视图更改是可以的。或者优选地,b)调用每个受影响的ListFragment中的函数以手动更新ListView。

我们将非常感谢您的帮助!

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2012-08-24 14:44:12

尝试记录每次Fragement被实例化时的标记。

代码语言:javascript
复制
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);
    }
}
票数 58
EN

Stack Overflow用户

发布于 2012-01-17 04:44:06

Barkside的答案适用于FragmentPagerAdapter,但不适用于FragmentStatePagerAdapter,因为它不会对传递给FragmentManager的片段设置标签。

使用FragmentStatePagerAdapter,我们似乎可以使用它的instantiateItem(ViewGroup container, int position)调用来解决问题。它返回对位置position处的片段的引用。如果FragmentStatePagerAdapter已经持有对有问题片段的引用,则instantiateItem只返回对该片段的引用,而不调用getItem()来再次实例化它。

因此,假设我当前正在查看片段#50,并且想要访问片段#49。因为它们很接近,所以很有可能#49已经实例化了。所以,

代码语言:javascript
复制
ViewPager pager = findViewById(R.id.viewpager);
FragmentStatePagerAdapter a = (FragmentStatePagerAdapter) pager.getAdapter();
MyFragment f49 = (MyFragment) a.instantiateItem(pager, 49)
票数 257
EN

Stack Overflow用户

发布于 2011-09-13 04:18:30

好吧,我想我已经找到了一种方法来执行我自己的问题中的请求b),所以我将分享给其他人的利益。viewpager内的片段标记的格式为"android:switcher:VIEWPAGER_ID:INDEX",其中VIEWPAGER_IDR.id.viewpager布局中的索引,而INDEX是视图页中的位置。因此,如果位置已知(例如0),我可以在updateFragments()中执行

代码语言:javascript
复制
      HomeListFragment fragment = 
          (HomeListFragment) getSupportFragmentManager().findFragmentByTag(
                       "android:switcher:"+R.id.viewpager+":0");
      if(fragment != null)  // could be null if not instantiated yet
      {
         if(fragment.getView() != null) 
         {
            // no need to call if fragment's onDestroyView() 
            //has since been called.
            fragment.updateDisplay(); // do what updates are required
         }
      }

我不知道这是不是一种有效的方法,但在提出更好的建议之前,它会起作用的。

票数 154
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7379165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档