前言

一般频繁切换Fragment会导致频繁的释放和创建,如果Fragment比较臃肿体验就非常不好了,这里分享一个方法。

声明

欢迎转载,但请保留文章原始出处:) 
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com

正文

一、应用场景

1、不使用ViewPager

2、不能用replace来切换Fragment,会导致Fragment释放(调用onDestroyView)

二、实现

1、xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >     <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1.0" >
    </FrameLayout>     <RadioGroup
        android:id="@+id/main_radio"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:gravity="bottom"
        android:layout_marginBottom="-6dp"
        android:orientation="horizontal" >         <RadioButton
            android:id="@+id/radio_button0"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_1" />         <RadioButton
            android:id="@+id/radio_button1"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_2" />         <RadioButton
            android:id="@+id/radio_button2"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_3" />         <RadioButton
            android:id="@+id/radio_button3"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_4" />         <RadioButton
            android:id="@+id/radio_button4"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_5" />
    </RadioGroup> </LinearLayout>

代码说明:

非常常见的底部放5个RadioButton,点击切换不同的Fragment。

2、Activity

为RadioButton设置setOnCheckedChangeListener事件,其他代码:

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {
            Fragment fragment = (Fragment) mFragmentPagerAdapter.instantiateItem(mContainer, buttonView.getId());
            mFragmentPagerAdapter.setPrimaryItem(mContainer, 0, fragment);
            mFragmentPagerAdapter.finishUpdate(mContainer);
        } 
    }     private FragmentPagerAdapter mFragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {         @Override
        public Fragment getItem(int position) {
            switch (position) {
            case R.id.radio_button1:
                return new Fragment1();
            case R.id.radio_button2:
                return new Fragment2();
            case R.id.radio_button3:
                return new Fragment3();
            case R.id.radio_button4:
                return new Fragment4();
            case R.id.radio_button0:
            default:
                return new Fragment0();
            }
        }         @Override
        public int getCount() {
            return 5;
        }
    };

代码说明:

instantiateItem从FragmentManager中查找Fragment,找不到就getItem新建一个,setPrimaryItem设置隐藏和显示,最后finishUpdate提交事务。

mContainer就是xml中的FrameLayout。

三、FragmentPagerAdapter核心代码

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }         final long itemId = getItemId(position);         // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }         return fragment;
    }     @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
                + " v=" + ((Fragment)object).getView());
        mCurTransaction.detach((Fragment)object);
    }     @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment)object;
        if (fragment != mCurrentPrimaryItem) {
            if (mCurrentPrimaryItem != null) {
                mCurrentPrimaryItem.setMenuVisibility(false);
                mCurrentPrimaryItem.setUserVisibleHint(false);
            }
            if (fragment != null) {
                fragment.setMenuVisibility(true);
                fragment.setUserVisibleHint(true);
            }
            mCurrentPrimaryItem = fragment;
        }
    }     @Override
    public void finishUpdate(ViewGroup container) {
        if (mCurTransaction != null) {
            mCurTransaction.commitAllowingStateLoss();
            mCurTransaction = null;
            mFragmentManager.executePendingTransactions();
        }
    }

FragmentPagerAdapter是support包自带的类。

四、注意

之前自己模拟ViewPager用attach、setMenuVisibility、setUserVisibleHint来控制Fragment的显示隐藏,经常会出现Fragment重叠现象,非常头疼,换了这个之后目前没有发现重叠现象。

五、文章后期维护

2013-12-01  上传示例代码:http://files.cnblogs.com/over140/SampleFragmentSwitch.zip

    @Override
    public void setMenuVisibility(boolean menuVisible) {
        super.setMenuVisibility(menuVisible);
        if (this.getView() != null)
            this.getView().setVisibility(menuVisible ? View.VISIBLE : View.GONE);
    }

重新做例子时发现自己也出不来效果了,后来发现少了这段代码。

2014-01-08 想实现本文的效果还是推荐直接使用ViewPager,通过自定义ViewPager禁用掉左右滑动和自动销毁即可,根据评论来看非正常情况下重影现象还是挺严重的。

结束

需要多看看源码,才能很好的解决问题。

【Android】保存Fragment切换状态的更多相关文章

  1. Android使得Fragment 切换时不重新实例化

    以前实现Fragment的切换都是用replace方法实现 public void startFragmentAdd(Fragment fragment) { FragmentManager frag ...

  2. android viewpager fragment切换时界面卡顿解决办法

    目前开发的程序在切换View时界面卡顿现象比较严重,影响用户体验,当前项目共就四个View,每个View也只是按钮,所以可以同时加载,不让其它view销毁. 只需在Adapter中重载destroyI ...

  3. Android下fragment切换的动画效果

    网上看到的例子,转过来记录一下,学习一下,感谢原作者的辛勤编码,效果非常好 基于Android3.0新增的动画api,效果很赞 共21种动画效果: <item>X轴缩放</item& ...

  4. Android中Fragment+ViewPager的配合使用

    官方推荐 ViewPager与Fragment一起使用,可以更加方便的管理每个Page的生命周期,这里有标准的适配器实现用于ViewPager和Fragment,涵盖最常见的用例.FragmentPa ...

  5. Android 进阶 Fragment 介绍和使用 (二)

    管理fragment 因为FragmentManager的API是在Android 3.0,也即API level 11开始引入的,所以对于之前的版本,需要使用support library中的Fra ...

  6. Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信

    以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3364728.html 我前两天写过一篇博客<Android使用Fragment来 ...

  7. Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信

    以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3360938.html 如新浪微博下面的标签切换功能,我以前也写过一篇博文(http:/ ...

  8. android fragment+ FragmentTabHost+viewpager 切换状态不保存的问题

    转载请注明出处:http://blog.csdn.net/djy1992/article/details/46674169 @author dujinyang 难得有时间上来写博客. fragment ...

  9. 保存和恢复 Android Fragment 的状态

    经过几年在 Android 应用开发中应用 Fragment 的努力之后,我必须要说尽管Fragment的概念非常优秀,但是它也同时带来了一堆问题.当我们处理实例的状态保存时就需要特别一件一件地修护好 ...

随机推荐

  1. PHP条件语句语法与示例

    一.if…else语句 语法: 1 if(条件){ …… } else{ …… } 2 if(条件){ …… } elseif(条件){ …… } else{ …… } 示例1: <?php & ...

  2. WinForm菜单和工具栏

    菜单和工具栏: 1.MenuStrip - 顶部菜单栏分割线:1输入- 2.右键插入 |SpearTOR 快捷键设置:每一个项右键属性的最下面可以设置快捷键不管选项隐藏还是菜单隐藏,快捷键都管用 2. ...

  3. Linq和Lamda表达式的简单处理方式

    一 什么是LINQ? LINQ即Language Integrated Query(语言集成查询),LINQ是集成到C#和Visual Basic.NET这些语言中用于提供查询数据能力的一个新特性. ...

  4. 新平台,新版本,ComponentOne 持续发力

    我们很高兴宣布2016年 V1 版本发布了,可免费下载试用. 今年ComponentOne 将聚焦WinForm.WPF.MVC.UWP平台和核心控件Flex家族. 本次发布主要包括UWP平台:Win ...

  5. Hewlett-Packard Enterprise 实习总结日记

    人生的第一份正式的实习工作时在HP,受益颇多.突然要离开了,还是非常舍不得的.在公司实习这半年多时间,写篇博客,对这期间的成长经历做一些总结.先说一个典故:我叫史蒂夫·乔布斯,我想找一些零件来做一台频 ...

  6. inflate的基本用法,类似于findviewbyId

    Inflate()作用就是将xml定义的一个布局找出来,但仅仅是找出来而且隐藏的,没有找到的同时并显示功能.最近做的一个项目就是这一点让我迷茫了好几天. android上还有一个与Inflate()类 ...

  7. HR人力资源战略流程制定

    HR人力资源战略 是指根据企业总体战略的要求,为适应企业生存和发展的需要,对企业人力资源进行开发,提高职工队伍的整体素质,从中发现和培养出一大批优秀人才,所进行的长远性的人力资源管理方面的专业谋划和方 ...

  8. HTML5的Server-Sent Events介绍

    body{ font: 16px/1.5em 微软雅黑,arial,verdana,helvetica,sans-serif; }       HTML5有一个Server-Sent Events(S ...

  9. GJM :C++ 网络编程 [转载]

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  10. 项目中应用eventbus解决的问题

    在项目开发过程中,往往有些功能表面看起来简单,但实际开发的结果非常复杂,仔细分析下原因发现很多都是因为附加了许多的额外功能. 真的简单吗? 比如我们对一个电商平台的商品数据做修改的功能来讲,其实非常简 ...