我无法更新ViewPager中的内容。

FragmentPagerAdapter类中instantiateItem()和getItem()方法的正确用法是什么?

我只使用getItem()来实例化并返回我的片段:

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

这很有效。但我不能改变内容。

所以我发现这个:ViewPager PagerAdapter没有更新视图

我的方法是对instantiateItem()方法中的任何实例化视图使用setTag()方法

现在我想实现instantiateItem()来实现这一点。但我不知道我必须返回什么(类型是对象)和什么与getItem(int位置)的关系?

我读了参考资料:

public abstract Fragment getItem (int position) Return the Fragment associated with a specified position. public Object instantiateItem (ViewGroup container, int position) Create the page for the given position. The adapter is responsible for adding the view to the container given here, although it only must ensure this is done by the time it returns from finishUpdate(ViewGroup). Parameters container The containing View in which the page will be shown. position The page position to be instantiated. Returns Returns an Object representing the new page. This does not need to be a View, but can be some other container of the page.

但我还是不明白

这是我的代码。我用的是v4支持包。

查看页面测试

public class ViewPagerTest extends FragmentActivity {
    private ViewPager pager;
    private MyFragmentAdapter adapter; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pager1);

        pager = (ViewPager)findViewById(R.id.slider);

        String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};

        adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        pager.setAdapter(adapter);

        ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });
    }

    private void reload() {
        String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
        //adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        adapter.setData(data);
        adapter.notifyDataSetChanged();
        pager.invalidate();

        //pager.setCurrentItem(0);
    }
}

我的片段适配器

class MyFragmentAdapter extends FragmentPagerAdapter {
    private int slideCount;
    private Context context;
    private String[] data;

    public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
        super(fm);
        this.slideCount = slideCount;
        this.context = context;
        this.data = data;
    }

    @Override
    public Fragment getItem(int position) {
        return new MyFragment(data[position], context);
    }

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

    public void setData(String[] data) {
        this.data = data;
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}

我的片段

public final class MyFragment extends Fragment {
    private String text;

    public MyFragment(String text, Context context) {
        this.text = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide, null);
        ((TextView)view.findViewById(R.id.text)).setText(text);

        return view;
    }
}

这里还有一个人也有类似的问题,没有答案 http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html


当前回答

你需要改变instantiateItem的mFragments元素getItemPosition。

    if (mFragments.size() > position) {
        Fragment f = mFragments.get(position);

        if (f != null) {
            int newPosition = getItemPosition(f);
            if (newPosition == POSITION_UNCHANGED) {
                return f;
            } else if (newPosition == POSITION_NONE) {
                mFragments.set(position, null);
            } else {
                mFragments.set(newPosition, f);
            }
        }
    }

基于AndroidX FragmentStatePagerAdapter.java,因为mFragments的元素位置在调用notifyDataSetChanged()时不会改变。

来源: https://github.com/cuichanghao/infivt/blob/master/library/src/main/java/cc/cuichanghao/library/FragmentStatePagerChangeableAdapter.java

例子: https://github.com/cuichanghao/infivt/blob/master/app/src/main/java/cc/cuichanghao/infivt/MainActivityChangeablePager.kt

您可以运行这个项目来确认如何工作。 https://github.com/cuichanghao/infivt

其他回答

这个解决方案并不适用于所有人,但在我的例子中,我的ViewPager中的每个Fragment都是一个不同的类,并且一次只存在其中一个。

有了这个约束,这个解决方案是安全的,应该可以安全地在生产中使用。

private void updateFragment(Item item) {

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for (Fragment fragment : fragments) {

        if (fragment instanceof MyItemFragment && fragment.isVisible()) {
            ((MyItemFragment) fragment).update(item);
        }

    }
}

如果您有同一个片段的多个版本,您可以使用相同的策略来调用这些片段上的方法,以确定它是否是您希望更新的片段。

对于那些仍然面临同样的问题,我以前遇到的时候,我有一个ViewPager与7个片段。这些片段默认从API服务加载英语内容,但这里的问题是,我想从设置活动和完成后更改语言 设置活动我想ViewPager在主活动刷新片段,以匹配从用户的语言选择和加载阿拉伯语内容,如果用户选择阿拉伯语在这里,我所做的工作从第一次

1-你必须使用FragmentStatePagerAdapter如上所述。

2-在mainActivity我覆盖onResume,并做以下

if (!(mPagerAdapter == null)) {
    mPagerAdapter.notifyDataSetChanged();
}

3-i覆盖了mPagerAdapter中的getItemPosition(),并使其返回POSITION_NONE。

@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}

工作很有魅力

而不是从getItemPosition()返回POSITION_NONE并引起完整的视图重建,这样做:

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(updateData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

你的片段应该实现UpdateableFragment接口:

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

以及界面:

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

你的数据类:

public class UpdateData {
    //whatever you want here
}

在代码中的notifyDataSetChanged()之后尝试在ViewPager上销毁drawingcache()。

你需要改变instantiateItem的mFragments元素getItemPosition。

    if (mFragments.size() > position) {
        Fragment f = mFragments.get(position);

        if (f != null) {
            int newPosition = getItemPosition(f);
            if (newPosition == POSITION_UNCHANGED) {
                return f;
            } else if (newPosition == POSITION_NONE) {
                mFragments.set(position, null);
            } else {
                mFragments.set(newPosition, f);
            }
        }
    }

基于AndroidX FragmentStatePagerAdapter.java,因为mFragments的元素位置在调用notifyDataSetChanged()时不会改变。

来源: https://github.com/cuichanghao/infivt/blob/master/library/src/main/java/cc/cuichanghao/library/FragmentStatePagerChangeableAdapter.java

例子: https://github.com/cuichanghao/infivt/blob/master/app/src/main/java/cc/cuichanghao/infivt/MainActivityChangeablePager.kt

您可以运行这个项目来确认如何工作。 https://github.com/cuichanghao/infivt