关于FragmentPagerAdapter通知数据改变不刷新的问题

    xiaoxiao2021-12-14  19

    FragmentPagerAdapter刷新fragment最完美解决方案

        先感谢kingjxl2006的博客文章《Android FragmentPagerAdapter数据刷新notifyDataSetChanged没效果研究》http://blog.sina.com.cn/s/blog_783ede03010173b4.html,没有他的抛砖引玉,就没有这篇博文。

        好,切入正题,正如上文所说的那样,在fragmentpageadapter的instantiateItem方法里,他会先去FragmentManager里面去查找有没有相关的fragment如果有就直接使用如果没有才会触发fragmentpageadapter的getItem方法获取一个fragment。所以你更新fragments集合是没有作用的。引用 kingjxl2006的 文章里的代码如下:                 // Do we already have this fragment?         String name = makeFragmentName(container.getId(), position);         Fragment fragment = mFragmentManager.findFragmentByTag(name);         if (fragment != null) {             if (DEBUG) Log.v(TAG, "Attaching item #" + position + ": f=" + fragment);             mCurTransaction.attach(fragment);         } else {             fragment = getItem(position);             if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);             mCurTransaction.add(container.getId(), fragment,                     makeFragmentName(container.getId(), position));         }

        kingjxl2006的办法是清除FragmentManager里面全部缓存的fragment。这很暴力我不赞同,全部清除会造成fragment重新加载,造成不必要的性能损失。

             这个方案还是在instantiateItem方法里作文章,代码如下:

    @Override

    public Object instantiateItem(ViewGroup Container,int position) {

       //得到缓存的fragment

        Fragment fragment = (Fragment)super.instantiateItem(container,

               position);

       //得到tag 

        String fragmentTag = fragment.getTag();         

     

       if (fragmentsUpdateFlag[position %fragmentsUpdateFlag.length]) {

          //如果这个fragment需要更新

          

           FragmentTransaction ft =fm.beginTransaction();

          //移除旧的fragment

           ft.remove(fragment);

          //换成新的fragment

           fragment =fragments[position %fragments.length];

          //添加新fragment时必须用前面获得的tag 

           ft.add(container.getId(), fragment, fragmentTag);

           ft.attach(fragment);

           ft.commit();

          

          //复位更新标志

          fragmentsUpdateFlag[position %fragmentsUpdateFlag.length] =false;

        }

     

       return fragment;

    }

             代码注释得很清楚了,主要思路就是用新的fragment替换FragmentManager里缓存的旧的fragment,重点解释❶的地方,看kingjxl2006文章里的两条代码:         String name = makeFragmentName(container.getId(), position);         Fragment fragment = mFragmentManager.findFragmentByTag(name);    说明fragmentpageadapter内部是用tag识别fragment的,并且有它自己的一套算法用于生成tag,所以我们这里必须用它生成的tag来添加新的fragment,否则fragmentpageadapter就无法识别这个新的fragment。     fragmentsUpdateFlag如其名,是一个用来标识哪个fragment需要更新的boolean类型的数组。     很多网友提问fm是什么东西?其实就是一个FragmentManager,在构造的时候传入即可:     class MyFragmentPagerAdapter extends FragmentPagerAdapter {         FragmentManager fm;         MyFragmentPagerAdapter(FragmentManager fm) {                super(fm);                this.fm = fm;         }         ……     下面贴完整一点的代码,以照顾新同学们: package com.example.mainframework03; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.Log; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.LinearLayout; public class MainActivity extends FragmentActivity implements FragmentEvent.OnEventListener { ViewPager viewPager; FragmentPagerAdapter adapter; MainTab01 tab01 = new MainTab01(); MainTab02 tab02 = new MainTab02(); MainTab03 tab03 = new MainTab03(); MainTab04 tab04 = new MainTab04(); MainTab05 tab05 = new MainTab05(); Fragment[] fragments = { tab01, tab02, tab03, tab04 }; boolean[] fragmentsUpdateFlag = { false, false, false, false }; /** * 底部四个按钮 */ private LinearLayout tabBtnWeixin; private LinearLayout tabBtnFrd; private LinearLayout tabBtnAddress; private LinearLayout tabBtnSettings; Handler mainHandler = new Handler() { /* * (非 Javadoc) * @see android.os.Handler#handleMessage(android.os.Message) */ @Override public void handleMessage(Message msg) { // TODO 自动生成的方法存根 super.handleMessage(msg); switch (msg.what) { case MSG.INTO_05: fragments[3] = tab05; fragmentsUpdateFlag[3] = true; adapter.notifyDataSetChanged(); break; default: } } }; class MyFragmentPagerAdapter extends FragmentPagerAdapter { FragmentManager fm; MyFragmentPagerAdapter(FragmentManager fm) { super(fm); this.fm = fm; } @Override public int getCount() { return fragments.length; } @Override public Fragment getItem(int position) { Fragment fragment = fragments[position % fragments.length]; Log.i(Common.TAG, "getItem:position=" + position + ",fragment:" + fragment.getClass().getName() + ",fragment.tag=" + fragment.getTag()); return fragments[position % fragments.length]; } @Override public int getItemPosition(Object object) { return POSITION_NONE; } @Override public Object instantiateItem(ViewGroup container, int position) { //得到缓存的fragment Fragment fragment = (Fragment) super.instantiateItem(container, position); //得到tag,这点很重要 String fragmentTag = fragment.getTag(); if (fragmentsUpdateFlag[position % fragmentsUpdateFlag.length]) { //如果这个fragment需要更新 FragmentTransaction ft = fm.beginTransaction(); //移除旧的fragment ft.remove(fragment); //换成新的fragment fragment = fragments[position % fragments.length]; //添加新fragment时必须用前面获得的tag,这点很重要 ft.add(container.getId(), fragment, fragmentTag); ft.attach(fragment); ft.commit(); //复位更新标志 fragmentsUpdateFlag[position % fragmentsUpdateFlag.length] = false; } return fragment; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.id_viewpager); tabBtnWeixin = (LinearLayout) findViewById(R.id.id_tab_bottom_weixin); tabBtnFrd = (LinearLayout) findViewById(R.id.id_tab_bottom_friend); tabBtnAddress = (LinearLayout) findViewById(R.id.id_tab_bottom_contact); tabBtnSettings = (LinearLayout) findViewById(R.id.id_tab_bottom_setting); adapter = new MyFragmentPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter); viewPager.setOnPageChangeListener(new OnPageChangeListener() { private int currentIndex; @Override public void onPageSelected(int position) { resetTabBtn(); switch (position) { case 0: ((ImageButton) tabBtnWeixin .findViewById(R.id.btn_tab_bottom_weixin)) .setImageResource(R.drawable.tab_weixin_pressed); break; case 1: ((ImageButton) tabBtnFrd .findViewById(R.id.btn_tab_bottom_friend)) .setImageResource(R.drawable.tab_find_frd_pressed); break; case 2: ((ImageButton) tabBtnAddress .findViewById(R.id.btn_tab_bottom_contact)) .setImageResource(R.drawable.tab_address_pressed); break; case 3: ((ImageButton) tabBtnSettings .findViewById(R.id.btn_tab_bottom_setting)) .setImageResource(R.drawable.tab_settings_pressed); break; } currentIndex = position; } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }); } protected void resetTabBtn() { ((ImageButton) tabBtnWeixin.findViewById(R.id.btn_tab_bottom_weixin)) .setImageResource(R.drawable.tab_weixin_normal); ((ImageButton) tabBtnFrd.findViewById(R.id.btn_tab_bottom_friend)) .setImageResource(R.drawable.tab_find_frd_normal); ((ImageButton) tabBtnAddress.findViewById(R.id.btn_tab_bottom_contact)) .setImageResource(R.drawable.tab_address_normal); ((ImageButton) tabBtnSettings.findViewById(R.id.btn_tab_bottom_setting)) .setImageResource(R.drawable.tab_settings_normal); } @Override public void onEvent(int what, Bundle data, Object object) { // TODO 自动生成的方法存根 mainHandler.sendEmptyMessage(what); } }     我的这个例程是在鸿洋_大大(http://blog.csdn.net/lmj623565791/article/details/24740977)的基础上改来的,再此感谢鸿洋_大大。    下载源码http://download.csdn.net/download/z13759561330/8114191 上面有些不靠谱,下面链接靠谱的: 点击打开链接
    转载请注明原文地址: https://ju.6miu.com/read-969290.html

    最新回复(0)