本文翻译自:Update ViewPager dynamically?

I can't update the content in ViewPager. 我无法更新ViewPager中的内容。

What is the correct usage of methods instantiateItem() and getItem() in FragmentPagerAdapter class? FragmentPagerAdapter类中的方法instantiateItem()和getItem()的正确用法是什么?

I was using only getItem() to instantiate and return my fragments: 我只使用getItem()实例化并返回我的片段:

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

This worked well. 这很好用。 Except I can't change the content. 除了我无法改变内容。

So I found this: ViewPager PagerAdapter not updating the View 所以我发现了这个: ViewPager PagerAdapter没有更新View

"My approach is to use the setTag() method for any instantiated view in the instantiateItem() method" “我的方法是对instantiateItem()方法中的任何实例化视图使用setTag()方法”

Now I want to implement instantiateItem() to do that. 现在我想实现instantiateItem()来做到这一点。 But I don't know what I have to return (the type is Object) and what is the relation with getItem(int position)? 但是我不知道我要返回什么(类型是Object)以及与getItem(int position)的关系是什么?

I read the reference : 我读了参考资料 :

  • public abstract Fragment getItem (int position) public abstract Fragment getItem(int position)

    Return the Fragment associated with a specified position. 返回与指定位置关联的片段。

  • public Object instantiateItem (ViewGroup container, int position) public Object instantiateItem(ViewGroup容器,int位置)

    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). 适配器负责将视图添加到此处给出的容器,但它必须确保在从finishUpdate(ViewGroup)返回时完成此操作。 Parameters 参数

    container The containing View in which the page will be shown. 容器包含将在其中显示页面的View。 position The page position to be instantiated. position要实例化的页面位置。

    Returns 返回

    Returns an Object representing the new page. 返回表示新页面的Object。 This does not need to be a View, but can be some other container of the page. 这不需要是View,但可以是页面的其他容器。

but I still don't get it. 但我仍然没有得到它。

Here's my code. 这是我的代码。 I'm using support package v4. 我正在使用支持包v4。

ViewPagerTest ViewPagerTest

public class ViewPagerTest extends FragmentActivity {private ViewPager pager;private MyFragmentAdapter adapter; @Overridepublic 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() {@Overridepublic 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 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;}@Overridepublic Fragment getItem(int position) {return new MyFragment(data[position], context);}@Overridepublic int getCount() {return slideCount;}public void setData(String[] data) {this.data = data;}@Overridepublic int getItemPosition(Object object) {return POSITION_NONE;}
}

MyFragment MyFragment

public final class MyFragment extends Fragment {private String text;public MyFragment(String text, Context context) {this.text = text;}@Overridepublic 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;}
}

Here is also somebody with a similar problem, no answers http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html 这里也有类似问题的人,没有答案http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html


#1楼

参考:https://stackoom.com/question/jWSm/动态更新ViewPager


#2楼

When using FragmentPagerAdapter or FragmentStatePagerAdapter, it is best to deal solely with getItem() and not touch instantiateItem() at all. 使用FragmentPagerAdapter或FragmentStatePagerAdapter时,最好只处理getItem()而不是触及instantiateItem() The instantiateItem() - destroyItem() - isViewFromObject() interface on PagerAdapter is a lower-level interface that FragmentPagerAdapter uses to implement the much simpler getItem() interface. 在PagerAdapter上的instantiateItem() - destroyItem() - isViewFromObject()接口是FragmentPagerAdapter用来实现更简单的getItem()接口的低级接口。

Before getting into this, I should clarify that 在进入这个之前,我应该澄清一下

if you want to switch out the actual fragments that are being displayed, you need to avoid FragmentPagerAdapter and use FragmentStatePagerAdapter. 如果要切换显示的实际片段,则需要避免使用FragmentPagerAdapter并使用FragmentStatePagerAdapter。

An earlier version of this answer made the mistake of using FragmentPagerAdapter for its example - that won't work because FragmentPagerAdapter never destroys a fragment after it's been displayed the first time. 这个答案的早期版本错误地将FragmentPagerAdapter用于它的示例 - 这将无法工作,因为FragmentPagerAdapter在第一次显示片段后从不销毁片段。

I don't recommend the setTag() and findViewWithTag() workaround provided in the post you linked. 我不建议您链接的帖子中提供的setTag()findViewWithTag()变通方法。 As you've discovered, using setTag() and findViewWithTag() doesn't work with fragments, so it's not a good match. 正如您所发现的,使用setTag()findViewWithTag()不能使用片段,因此它不是很好的匹配。

The right solution is to override getItemPosition() . 正确的解决方案是覆盖getItemPosition() When notifyDataSetChanged() is called, ViewPager calls getItemPosition() on all the items in its adapter to see whether they need to be moved to a different position or removed. notifyDataSetChanged()被调用,调用ViewPager getItemPosition()在其适配器的所有项目,看他们是否需要移动到不同的位置或删除。

By default, getItemPosition() returns POSITION_UNCHANGED , which means, "This object is fine where it is, don't destroy or remove it." 默认情况下, getItemPosition()返回POSITION_UNCHANGED ,这表示“此对象很好,不要销毁或删除它”。 Returning POSITION_NONE fixes the problem by instead saying, "This object is no longer an item I'm displaying, remove it." 返回POSITION_NONE修复问题,而是说:“此对象不再是我正在显示的项目,将其删除。” So it has the effect of removing and recreating every single item in your adapter. 因此它具有删除和重新创建适配器中每个项目的效果。

This is a completely legitimate fix! 这是一个完全合法的修复! This fix makes notifyDataSetChanged behave like a regular Adapter without view recycling. 此修复使notifyDataSetChanged的行为类似于常规适配器而没有视图回收。 If you implement this fix and performance is satisfactory, you're off to the races. 如果您实施此修复程序并且性能令人满意,那么您将参加比赛。 Job done. 任务完成。

If you need better performance, you can use a fancier getItemPosition() implementation. 如果您需要更好的性能,可以使用更高级的getItemPosition()实现。 Here's an example for a pager creating fragments off of a list of strings: 以下是分页器从字符串列表中创建片段的示例:

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

With this implementation, only fragments displaying new titles will get displayed. 通过此实现,将仅显示显示新标题的片段。 Any fragments displaying titles that are still in the list will instead be moved around to their new position in the list, and fragments with titles that are no longer in the list at all will be destroyed. 显示仍在列表中的标题的任何片段将被移动到列表中的新位置,并且将销毁具有不再在列表中的标题的片段。

What if the fragment has not been recreated, but needs to be updated anyway? 如果片段尚未重新创建,但仍需要更新,该怎么办? Updates to a living fragment are best handled by the fragment itself. 生命片段的更新最好由片段本身处理。 That's the advantage of having a fragment, after all - it is its own controller. 毕竟这是拥有片段的优势 - 它是它自己的控制器。 A fragment can add a listener or an observer to another object in onCreate() , and then remove it in onDestroy() , thus managing the updates itself. 片段可以将监听器或观察者添加到onCreate()另一个对象,然后在onDestroy()中将其删除,从而自行管理更新。 You don't have to put all the update code inside getItem() like you do in an adapter for a ListView or other AdapterView types. 您不必像在ListView或其他AdapterView类型的适配器中那样将所有更新代码放在getItem()

One last thing - just because FragmentPagerAdapter doesn't destroy a fragment doesn't mean that getItemPosition is completely useless in a FragmentPagerAdapter. 最后一件事 - 只是因为FragmentPagerAdapter没有销毁片段并不意味着getItemPosition在FragmentPagerAdapter中完全没用。 You can still use this callback to reorder your fragments in the ViewPager. 您仍然可以使用此回调来重新排序ViewPager中的片段。 It will never remove them completely from the FragmentManager, though. 但它永远不会从FragmentManager中完全删除它们。


#3楼

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


#4楼

Instead of returning POSITION_NONE from getItemPosition() and causing full view recreation, do this: 而不是从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);
}

Your fragments should implement UpdateableFragment interface: 您的片段应该实现UpdateableFragment接口:

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

and the interface: 和界面:

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

Your data class: 你的数据类:

public class UpdateData {//whatever you want here
}

#5楼

I have encountered this problem and finally solved it today, so I write down what I have learned and I hope it is helpful for someone who is new to Android's ViewPager and update as I do. 我遇到了这个问题,今天终于解决了,所以我写下了我所学到的东西,希望对Android的ViewPager有所帮助并像我一样更新。 I'm using FragmentStatePagerAdapter in API level 17 and currently have just 2 fragments. 我在API级别17中使用FragmentStatePagerAdapter ,目前只有2个片段。 I think there must be something not correct, please correct me, thanks. 我认为必定有些不正确的地方,请指正,谢谢。

  1. Serialized data has to be loaded into memory. 必须将序列化数据加载到内存中。 This can be done using a CursorLoader / AsyncTask / Thread . 这可以使用CursorLoader / AsyncTask / Thread Whether it's automatically loaded depends on your code. 它是否自动加载取决于您的代码。 If you are using a CursorLoader , it's auto-loaded since there is a registered data observer. 如果您使用CursorLoader ,它会自动加载,因为有一个注册的数据观察者。

  2. After you call viewpager.setAdapter(pageradapter) , the adapter's getCount() is constantly called to build fragments. 调用viewpager.setAdapter(pageradapter) ,将不断调用适配器的getCount()来构建片段。 So if data is being loaded, getCount() can return 0, thus you don't need to create dummy fragments for no data shown. 因此,如果正在加载数据, getCount()可以返回0,因此您不需要为没有显示的数据创建虚拟片段。

  3. After the data is loaded, the adapter will not build fragments automatically since getCount() is still 0, so we can set the actually loaded data number to be returned by getCount() , then call the adapter's notifyDataSetChanged() . 加载数据后,适配器将不会自动构建片段,因为getCount()仍为0,因此我们可以设置getCount()返回的实际加载的数据编号,然后调用适配器的notifyDataSetChanged() ViewPager begin to create fragments (just the first 2 fragments) by data in memory. ViewPager开始按内存中的数据创建片段(只是前2个片段)。 It's done before notifyDataSetChanged() is returned. 这是在返回notifyDataSetChanged()之前完成的。 Then the ViewPager has the right fragments you need. 然后, ViewPager拥有您需要的正确片段。

  4. If the data in the database and memory are both updated (write through), or just data in memory is updated (write back), or only data in the database is updated. 如果数据库和内存中的数据都已更新(直写),或者只更新内存中的数据(写回),或者只更新数据库中的数据。 In the last two cases if data is not automatically loaded from the database to memory (as mentioned above). 在最后两种情况下,如果数据没有自动从数据库加载到内存(如上所述)。 The ViewPager and pager adapter just deal with data in memory. ViewPager和寻呼机适配器只处理内存中的数据。

  5. So when data in memory is updated, we just need to call the adapter's notifyDataSetChanged() . 因此,当内存中的数据更新时,我们只需要调用适配器的notifyDataSetChanged() Since the fragment is already created, the adapter's onItemPosition() will be called before notifyDataSetChanged() returns. Nothing needs to be done in getItemPosition() . Then the data is updated. 由于片段已经创建,因此在notifyDataSetChanged()返回之前将调用适配器的onItemPosition() 。在getItemPosition()getItemPosition()任何操作。然后更新数据。


#6楼

I had a similar problem but don't want to trust on the existing solutions (hard coded tag names etc.) and I couldn't make M-WaJeEh's solution work for me. 我有类似的问题,但不想信任现有的解决方案(硬编码标签名称等),我不能让M-WaJeEh的解决方案适合我。 Here is my solution: 这是我的解决方案:

I keep references to the fragments created in getItem in an array. 我保留了对数组中getItem中创建的片段的引用。 This works fine as long as the activity is not destroyed due to configurationChange or lack of memory or whatever (--> when coming back to the activity, fragments return to their last state without 'getItem' being called again and thus without updating the array). 只要活动没有因为configurationChange或缺少内存或其他原因而被破坏,这种方法就可以正常工作了( - >当回到活动时,片段返回到它们的最后状态而没有再次调用'getItem',因此没有更新数组)。

To avoid this problem I implemented instantiateItem(ViewGroup, int) and update my array there, like this: 为了避免这个问题,我实现了instantiateItem(ViewGroup,int)并在那里更新我的数组,如下所示:

        @Overridepublic 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;}

So, on the one hand I'm happy that I found a solution that works for me and wanted to share it with you, but I also wanted to ask whether somebody else tried something similar and whether there is any reason why I shouldn't do it like that? 所以,一方面我很高兴我找到了一个适合我的解决方案并希望与你分享,但我也想问一下其他人是否尝试了类似的东西以及是否有任何理由我不应该这样做吗? So far it works very good for me... 到目前为止它对我来说非常好......

动态更新ViewPager?相关推荐

  1. android listview动态添加viewpager,向 ViewPager 中添加 包含 ListView 的 Fragment

    对与fragment就不说什么了,直接看API手册吧,亲. 向 ViewPager 中添加 包含 ListView 的 Fragment 的过程比较麻烦.他所表现的效果就是新闻客户端的滑动翻页效果. ...

  2. 仿百度壁纸客户端(五)——实现搜索动画GestureDetector手势识别,动态更新搜索关键字

    仿百度壁纸客户端(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Frag ...

  3. 仿百度壁纸client(五)——实现搜索动画GestureDetector手势识别,动态更新搜索keyword...

    仿百度壁纸client(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 百度壁纸系列 仿百度壁纸client(一)--主框架搭建,自己定义Tab + ViewPager ...

  4. 仿百度壁纸客户端(五)——实现搜索动画GestureDetector手势识别,动态更新搜索关键字...

    仿百度壁纸客户端(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Frag ...

  5. 动态更新 AGS Cache

    作者:Flyingis 提升ArcGIS Server访问速度最佳的方式是Cache,将所有图层切片保存在服务器,客户端请求时直接访问cache好的图片,这里分为两种情况,一是所有图层都做cache, ...

  6. android asynctask源码分析,Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)...

    本文实例讲述了Android通过Handler与AsyncTask两种方式动态更新ListView的方法.分享给大家供大家参考,具体如下: 有时候我们需要修改已经生成的列表,添加或者修改数据,noti ...

  7. 动态添加跨行表格_学会这2招,轻松搞定数据透视表动态更新,效率猛增一倍...

    私信回复关键词[福利],获取丰富办公资源,助你高效办公早下班! Hello,大家好,我是最近在研究数据透视表的小爽~ 最近,我收到了一个学员的求助: 简单归纳一下,这个问题就是: 如何能让数据透视表的 ...

  8. aaynctask控制多个下载进度_AsyncTask用法解析-下载文件动态更新进度条

    1. 泛型 AysncTask Params:启动任务时传入的参数,通过调用asyncTask.execute(param)方法传入. Progress:后台任务执行的进度,若不用显示进度条,则不需要 ...

  9. Centos DNS服务(二)-bind主从配置与基于TSIG加密的动态更新

    DNS的主从配置 DNS从服务器也叫辅服DNS服务器,如果网络上某个节点只有一台DNS服务器的话,首先服务器的抗压能力是有限的,当压力达到一定的程度,服务器就可能会宕机罢工, 其次如果这台服务器出现了 ...

最新文章

  1. 接口(interface)
  2. 下列不可以判断网页是否正常打开的是_打开视频卡、无法加载原因查找
  3. maven各个属性参数详解
  4. laravel-admin form中的数据,在提交后,保存前,获取并进行编辑
  5. 通过Mybatis获取mysql表中重复记录的方法
  6. 网页无法正常显示Lato字体,绕路而行
  7. Cmder安装使用篇
  8. 筑业单机版建材管理软件
  9. 【esp32】esp-ali-smartliving源码分析
  10. 【C语言】数字直角三角形,数字矩阵,蛇形数组
  11. 【JavaSE进阶(上)】自学笔记 记得收藏时时回顾
  12. 技巧 | 清理电脑垃圾
  13. 中心差分法编程C语言,中心差分法的基本理论与程序设计.docx
  14. hadoop配置过程中可能会出的问题localhost: root@localhost: Permission denied (publickey,password).
  15. 网上书店订单流程c语言源代码,网上书店的设计及实现.doc
  16. 3.22 3.23 二九三十C语言基础
  17. 软件行业中的鱼骨图运用
  18. 【斐波那契数列】母牛繁殖
  19. 一个北京人的买房血泪史:我不想一辈子做房奴!
  20. 计算机无法搜索到打印机驱动,添加打印机时搜索不到如何解决_电脑搜不到打印机设备的处理办法-系统城...

热门文章

  1. radioGroup中radiobutton不能互斥问题
  2. 安卓开发重磅炸弹!程序员福利!《高级Kotlin强化实战学习手册(附Demo)》开放下载!
  3. opengl之自动纹理
  4. Android stadio bug
  5. 第十五周程序阅读-范型程序设计(4)
  6. Android10.0系统启动之Launcher(桌面)启动流程-[Android取经之路]
  7. Zxing二维码开源项目
  8. UIView及其分类的属性方法定义
  9. iOS进阶之架构设计MVC(1)
  10. AutoML初创公司探智立方:模型的物竞天择与适者生存