Android 动态更新ViewPager?

Android 动态更新ViewPager?,android,android-fragments,android-viewpager,Android,Android Fragments,Android Viewpager,我无法更新ViewPager中的内容 FragmentPagerAdapter类中实例化Item()和getItem()方法的正确用法是什么 我只使用getItem()实例化并返回片段: @Override public Fragment getItem(int position) { return new MyFragment(context, paramters); } 这很有效。除了我不能改变内容 所以我发现: “我的方法是对InstanceItem()方法中的任何实例化视图使用

我无法更新ViewPager中的内容

FragmentPagerAdapter类中实例化Item()和getItem()方法的正确用法是什么

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

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}
这很有效。除了我不能改变内容

所以我发现:

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

现在我想实现instanceItem()来实现这一点。但是我不知道我必须返回什么(类型是Object)以及与getItem(int位置)的关系是什么

我读到:

  • 公共抽象片段getItem(int位置)

    返回与指定位置关联的片段

  • 公共对象实例化项(视图组容器,int位置)

    为给定位置创建页面。适配器负责将视图添加到此处给定的容器中,尽管它只需确保在从finishUpdate(ViewGroup)返回时完成此操作。 参数

    包含将在其中显示页面的视图的容器。 定位要实例化的页面位置

    返回

    返回表示新页的对象。这不需要是视图,但可以是页面的其他容器

但我还是不明白

这是我的密码。我正在使用支持包v4

ViewPagerTest

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

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;
    }
}
这里也有人有类似的问题,没有答案

使用FragmentPagerAdapter或FragmentStatePagerAdapter时,最好只处理
getItem()
,而不要触摸
InstanceItem()
。PagerAdapter上的
实例化Item()
-
destroyItem()
接口是FragmentPagerAdapter用于实现更简单的
getItem()
接口的低级接口

在讨论这个问题之前,我应该澄清一下

如果要切换显示的实际片段,需要避免使用FragmentPagerAdapter并使用 FragmentStatePagerAdapter.

这个答案的一个早期版本犯了一个错误,使用FragmentPagerAdapter作为例子——这不起作用,因为FragmentPagerAdapter在第一次显示片段后从不销毁它

我不推荐您链接的帖子中提供的
setTag()
findViewWithTag()
解决方法。正如您所发现的,使用
setTag()
findViewWithTag()
无法处理片段,因此这不是一个很好的匹配

正确的解决方案是重写
getItemPosition()
。调用
notifyDataSetChanged()
时,ViewPager会对其适配器中的所有项调用
getItemPosition()
,查看它们是否需要移动到其他位置或删除

默认情况下,
getItemPosition()
返回
POSITION\u UNCHANGED
,这意味着,“此对象在其所在位置很好,不要销毁或删除它。”返回
POSITION\u NONE
修复了问题,改为说:“此对象不再是我正在显示的项目,请将其删除。”因此,它可以删除并重新创建适配器中的每一项

这是一个完全合法的修复!此修复程序使notifyDataSetChanged的行为类似于常规适配器,无需视图回收。如果您实现了此修复并且性能令人满意,那么您就可以开始比赛了。工作完成了

如果需要更好的性能,可以使用更高级的
getItemPosition()
实现。下面是一个寻呼机从字符串列表中创建片段的示例:

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
    public int getCount() {
        return titles.size();
    }

    public Fragment getItem(int position) {
        MyFragment fragment = new MyFragment();
        fragment.setTitle(titles.get(position));
        return fragment;
    }

    public int getItemPosition(Object item) {
        MyFragment fragment = (MyFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }
});
ViewPager-pager=/*获取我的ViewPager*/;
//假设这里面有东西
最终ArrayList标题=新ArrayList();
FragmentManager fm=getSupportFragmentManager();
寻呼机设置适配器(新FragmentStatePagerAdapter(fm){
public int getCount(){
返回titles.size();
}
公共片段getItem(int位置){
MyFragment fragment=新的MyFragment();
fragment.setTitle(titles.get(position));
返回片段;
}
public int getItemPosition(对象项){
MyFragment fragment=(MyFragment)项;
String title=fragment.getTitle();
int position=titles.indexOf(title);
如果(位置>=0){
返回位置;
}否则{
返回位置\无;
}
}
});
在这个实现中,只会显示显示新标题的片段。任何显示仍在列表中的标题的片段都将被移动到列表中的新位置,而标题已完全不在列表中的片段将被销毁

如果片段尚未重新创建,但仍需要更新,该怎么办?对活动片段的更新最好由片段本身来处理。毕竟,这就是拥有片段的优势——它是自己的控制器。片段可以向
onCreate()
中的另一个对象添加侦听器或观察者,然后在
onDestroy()
中删除它,从而管理更新本身。您不必像在ListView或其他AdapterView类型的适配器中那样,将所有更新代码放入
getItem()


最后一件事——仅仅因为FragmentPagerAdapter不销毁片段并不意味着getItemPosition在FragmentPagerAdapter中完全无用。您仍然可以使用此回调对ViewPager中的片段重新排序。但是,它永远不会从FragmentManager中完全删除它们。

在代码中的
notifyDataSetChanged()
之后,在ViewPager上尝试
destroyDrawingCache()

而不是从
getItemPosition()
返回
POSITION\u 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);
}
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
}
        @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object o = super.instantiateItem(container, position);
        if(o instanceof FragmentX){
            myFragments[0] = (FragmentX)o;
        }else if(o instanceof FragmentY){
            myFragments[1] = (FragmentY)o;
        }else if(o instanceof FragmentZ){
            myFragments[2] = (FragmentZ)o;
        }
        return o;
    }
 public class myPagerAdapter extends FragmentPagerAdapter {
public class PagerItem {
private String mTitle;
private Fragment mFragment;


public PagerItem(String mTitle, Fragment mFragment) {
    this.mTitle = mTitle;
    this.mFragment = mFragment;
}
public String getTitle() {
    return mTitle;
}
public Fragment getFragment() {
    return mFragment;
}
public void setTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setFragment(Fragment mFragment) {
    this.mFragment = mFragment;
}

}
private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mPagerItems = pagerItems;
}
public void setPagerItems(ArrayList<PagerItem> pagerItems) {
    if (mPagerItems != null)
        for (int i = 0; i < mPagerItems.size(); i++) {
            mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
        }
    mPagerItems = pagerItems;
}
ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
    pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
    pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));

    mPagerAdapter.setPagerItems(pagerItems);
    mPagerAdapter.notifyDataSetChanged();
private class PagerAdapter extends FragmentStatePagerAdapter{
    Bundle oBundle;
    FragmentManager oFragmentManager;
    ArrayList<Fragment> oPooledFragments;

public PagerAdapter(FragmentManager fm) {
    super(fm);
    oFragmentManager=fm;

    }
@Override
public int getItemPosition(Object object) {

    Fragment oFragment=(Fragment)object;
    oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
    if(oPooledFragments.contains(oFragment))
        return POSITION_NONE;
    else
        return POSITION_UNCHANGED;
    } 
}
if (!(mPagerAdapter == null)) {
    mPagerAdapter.notifyDataSetChanged();
}
@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}
public class UpdateCountEvent {
    public final int count;

    public UpdateCountEvent(int count) {
        this.count = count;
    }
}
@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);  
    super.onStop();
}

public void onEvent(UpdateCountEvent event) {//get update message
    Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}
//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));
class PagerAdapter extends FragmentPagerAdapter {

    public boolean flag_refresh=false;

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int page) {
        FragmentsMain f;
        f=new FragmentsMain();
        f.page=page;
        return f;
    }

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

    @Override
    public int getItemPosition(Object item) {
        int page= ((FragmentsMain)item).page;

        if (page == 0 && flag_refresh) {
            flag_refresh=false;
            return POSITION_NONE;
        } else {
            return super.getItemPosition(item);
        }
    }

    @Override
    public void destroyItem(View container, int position, Object object) {

        ((ViewPager) container).removeView((View) object);
    }
}
 adapter=new PagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

@Override
protected void onResume() {
    super.onResume();

    if (adapter!=null) {
        adapter.flag_refresh=true;
        adapter.notifyDataSetChanged();
    }
}
public class FragmentsMain extends Fragment {

private Cursor cursor;
private static Context context;
public int page=-1;
private class MyAdapter extends FragmentStatePagerAdapter {

    // [Rest of implementation]

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {}

}
private void updateFragment(Item item) {

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

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

    }
}
@Override
public void notifyDataSetChanged() {
    mFragments.clear();
    super.notifyDataSetChanged();
}
if (position < mFragments.size()) {
    mFragments.set(position, null);
}
public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
    private static final String TAB1_TITLE = "Tab 1";
    private static final String TAB2_TITLE = "Tab 2";
    private static final String TAB3_TITLE = "Tab 3";

    private ArrayList<String> titles = new ArrayList<>();
    private Map<Fragment, Integer> fragmentPositions = new HashMap<>();


    public MyFragmentStatePageAdapter(FragmentManager fm) {
        super(fm);
    }


    public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
        titles.clear();

        if (showTab1) {
            titles.add(TAB1_TITLE);
        }
        if (showTab2) {
            titles.add(TAB2_TITLE);
        }
        if (showTab3) {
            titles.add(TAB3_TITLE);
        }
        notifyDataSetChanged();
    }


    @Override
    public int getCount() {
        return titles.size();
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;

        String tabName = titles.get(position);
        if (tabName.equals(TAB1_TITLE)) { 
            fragment =  Tab1Fragment.newInstance();
        } else if (tabName.equals(TAB2_TITLE)) {
            fragment =  Tab2Fragment.newInstance();
        } else if (tabName.equals(TAB3_TITLE)) {
            fragment =  Tab3Fragmen.newInstance();
        } 

        ((BaseFragment)fragment).setTitle(tabName);
        fragmentPositions.put(fragment, position);
        return fragment;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }

    @Override
    public int getItemPosition(Object item) {
        BaseFragment fragment = (BaseFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        Integer fragmentPosition = fragmentPositions.get(item);
        if (fragmentPosition != null && position == fragmentPosition) {
            return POSITION_UNCHANGED;
        } else {
            return POSITION_NONE;
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragmentPositions.remove(object);
    }
}
myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);
 public int getItemPosition(Object item) {
    if(item instanceof FirstFragment){
       return 0;
    }
    return POSITION_NONE;
 }
private boolean mIsUpdating = false;
public void setIsUpdating(boolean mIsUpdating) {
        this.mIsUpdating = mIsUpdating;
    }


@Override
public int getItemPosition(@NonNull Object object) {

    if (mIsUpdating) {
        return POSITION_NONE;
    }
    else {
        return super.getItemPosition(object);
    }
}
mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);
    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);
            }
        }
    }