zoukankan      html  css  js  c++  java
  • FragmentPagerAdapter刷新fragment最完美解决方案

    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)的基础上改来的,再此感谢鸿洋_大大。
     
  • 相关阅读:
    百度搜索技巧
    Redis汇总
    分享一个经验,代码打开mysql链接,执行存储过程时,提示:Table 'mysql.proc' doesn't exist
    WPF 重写微调自带的样式,ListView、DataGrid、TreeView等所有控件的默认样式
    WPF 图片抗锯齿,尤其是小图片更为严重
    通过鼠标事件,从鼠标点击的坐标寻找指定的控件
    重写TreeView,多层级节点下批量显示图片,图片支持缩略图和文件名列表切换,支持调用者动态匹配选中,支持外界拖入图片并添加到对应节点下
    重写TreeView,自定义图标,生成通行的下划线,取消默认获得焦点失去焦点的效果,并支持拖拽节点到外界
    四、C#入门—表达式与运算符
    三、C#入门—数据类型
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4503816.html
Copyright © 2011-2022 走看看