一 基本使用

Fragment依附于Activity使用,方面我们在一个页面里面切换显示多屏内容。

Activity管理Fragment有两种方式,通过FragmentTransacation这个类来管理fragment的显示、隐藏

1 replace方法

 FragmentTransaction transaction = mBaseActivity.getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fl_container, mCurrent).commit();

使用这种方法,可以避免出现fragment重叠问题。但每次执行replace时,fragment都会重新走一遍生命周期方法,会造成重复加载数据。不推荐使用。

2 hide,show,add方法

     private void switchFragment(Fragment from, Fragment to) {
if (mCurrent != to) {
mCurrent = to;
FragmentTransaction transaction = mBaseActivity.getSupportFragmentManager().beginTransaction();
// 判断目标fragment是否被add过
if (!to.isAdded()) {
transaction.hide(from).add(R.id.fl_container, to,to.getClass().getName()).commit();
} else {
transaction.hide(from).show(to).commit();
}
}
}

使用这种方法,避免了重新加载数据问题,但是会出现fragment重叠问题。

原因:当内存不足时,系统会回收宿主Activity,而Fragment实例并没有被一并回收,activity被回收时会主动调用onSaveInstanceState方法,保存视图层(View Hierarchy)及一些activity的数据。

二 重叠问题

通过onCreate中的参数savedInstanceState恢复了之前的fragment。此时的FragmentTransaction中的相当于又再次add了fragment进去的,之前保存的fragment也还在。hide()和show()方法对之前保存的fragment已经失效了。之前显示的fragment一直显示,所以出现了重叠的现象。解决方法:

首先,activity被系统收回,触发onSaveInstanceState(Bundle outState)方法,在outstate里,系统自动保存了fragment数据,手动保存当前显示的fragment索引

    private static final String SAVED_CURRENT_ID = "currentId";
private int currentIndex;
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
outState.putInt(SAVED_CURRENT_ID, currentIndex);//保存当前显示fragment索引
super.onSaveInstanceState(outState, outPersistentState);
}

其次,当重新进入activity时,走生命周期方法oncreae(Bundle savedInstanceState),saveInstanceState 包含了fragment数据,以及其他一些view的状态,和我们手动保存的数据,从bundle里取出fragment对象,避免重新实例化fragment,造成视图重叠

     @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//重启时防止fragment重叠
if (savedInstanceState != null) {
currentIndex = savedInstanceState.getInt(SAVED_CURRENT_ID, 0);
homeFragment = (HomeFragment) getSupportFragmentManager().findFragmentByTag(HomeFragment.class.getName());
newsFragment = (NewsFragment) getSupportFragmentManager().findFragmentByTag(NewsFragment.class.getName());
findFragment = (FindFragment) getSupportFragmentManager().findFragmentByTag(FindFragment.class.getName());
adminFragment = (AdminFragment) getSupportFragmentManager().findFragmentByTag(AdminFragment.class.getName());
} else {
initFragment();
}
intView();
} @Override
protected void intView() {
setTitle("主页");
radioGroup = (RadioGroup) findViewById(R.id.rg_main_bottom);
radioGroup.setOnCheckedChangeListener(occl);
((RadioButton) radioGroup.getChildAt(currentIndex)).setChecked(true);
}

最后,恢复选中fragment

     private RadioGroup.OnCheckedChangeListener occl = new RadioGroup.OnCheckedChangeListener() {

         @Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb_home:
setTitle("首页");
currentIndex = 0;
if (homeFragment == null) {
homeFragment = HomeFragment.newInstance(null, null);
}
switchFragment(mBackHandledFragment, homeFragment);
break;
case R.id.rb_news:
setTitle("新闻");
currentIndex = 1;
if (newsFragment == null) {
newsFragment = NewsFragment.newInstance(null, null);
}
switchFragment(mBackHandledFragment, newsFragment);
break;
case R.id.rb_find:
showTabSelectView();
currentIndex = 2;
if (findFragment == null) {
findFragment = FindFragment.newInstance(null, null);
}
switchFragment(mBackHandledFragment, findFragment);
break;
case R.id.rb_admin:
setTitle("我的");
currentIndex = 3;
if (adminFragment == null) {
adminFragment = AdminFragment.newInstance(null, null);
}
switchFragment(mBackHandledFragment, adminFragment);
break;
}
}
}; private void switchFragment(Fragment from, Fragment to) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (null == from) {
if (mBackHandledFragment != to) {
mBackHandledFragment = (BackHandledFragment) to;
if (!to.isAdded()) {
transaction.add(R.id.frameLayout_container, to, to.getClass().getName()).commit();
} else {
transaction.show(to).commit();
}
}
} else {
if (mBackHandledFragment != to) {
mBackHandledFragment = (BackHandledFragment) to;
// 判断目标fragment是否被add过
if (!to.isAdded()) {
transaction.hide(from).add(R.id.frameLayout_container, to, to.getClass().getName()).commit();
} else {
transaction.hide(from).show(to).commit();
}
}
}
}

Fragment 基础使用及重叠问题的更多相关文章

  1. 札记:Fragment基础

    Fragment概述 在Fragment出现之前,Activity是app中界面的基本组成单位,值得一提的是,作为四大组件之一,它是需要"注册"的.组件的特性使得一个Activit ...

  2. Fragment基础----信息传递

    如何通过activity来访问fragment的信息呢,我们可以通过一个实例来了解. 使用两个Fragment和一个activity管理 效果图: 第一个fragment来表示输入框 第二个fragm ...

  3. Fragment基础----生命周期

    Fragment生命周期和Activity对比 注意:在一个app的运行期间,前台的activity有时可能会被其他的视图组件打断,然后进入pause状态. 比如打开一个半透膜的activity (比 ...

  4. Fragment基础----创建

    1,Fragment的目的及应用场景 fragment 是3.0后引入的类,其字面翻译为“碎片”. 目的是将activity划分成许多单元再进行组合,可以根据不同分辨率屏幕,在不同状态下,灵活创建优化 ...

  5. android之Fragment基础详解(一)

      一.Fragment的设计哲学 Android在3.0中引入了fragments的概念,主要目的是用在大屏幕设备上--例如平板电脑上,支持更加动态和灵活的UI设计.平板电脑的屏幕比手机的大得多,有 ...

  6. Fragment基础讲解

    //新建一个碎片public class LeftFragment extends Fragment { @Override public View onCreateView(LayoutInflat ...

  7. Android Studio 单刷《第一行代码》系列 05 —— Fragment 基础

    前情提要(Previously) 本系列将使用 Android Studio 将<第一行代码>(书中讲解案例使用Eclipse)刷一遍,旨在为想入坑 Android 开发,并选择 Andr ...

  8. Android Fragment基础及使用

    同一个app内的界面切换 用Fragment比较合适,因为Activity比较重量级 Fragment 轻量级,切换灵活 --------------------------------------- ...

  9. Fragment 基础

    FragmentActivity与Activity区别 fragment是3.0以后的东西,为了在低版本中使用fragment就要用到android-support-v4.jar兼容包,而fragme ...

随机推荐

  1. [BZOJ 4668]冷战(带边权并查集+启发式合并)

    [BZOJ 4668]冷战(并查集+启发式合并) 题面 一开始有n个点,动态加边,同时查询u,v最早什么时候联通.强制在线 分析 用并查集维护连通性,每个点x还要另外记录tim[x],表示x什么时间与 ...

  2. Codeforces 1262F Wrong Answer on test 233(组合数)

    E1:设dp[i][j],表示在第i个位置的当前新状态超过原状态j分的方案数是dp[i][j],那么对于这种情况直接进行转移即可,如果a[i]==b[i]显然k种选择都可以,不影响j,如果不一样,这个 ...

  3. [LeetCode] 137. 只出现一次的数字 II

    题目链接 : https://leetcode-cn.com/problems/single-number-ii/ 题目描述: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三 ...

  4. 查看linux中所有用户的三种方式

    通过使用/etc/passwd 文件,getent命令,compgen命令这三种方法查看系统中用户的信息. Linux 系统中用户信息存放在/etc/passwd文件中. 这是一个包含每个用户基本信息 ...

  5. 区块链开源实现hyperledger fabric架构详解

    hyperledger fabric是区块链中联盟链的优秀实现,主要代码由IBM.Intel.各大银行等贡献,目前v1.1版的kafka共识方式可达到1000/s次的吞吐量.本文中我们依次讨论:区块链 ...

  6. 【源码解读】cycleGAN(二) :训练

    源码地址:https://github.com/aitorzip/PyTorch-CycleGAN 训练的代码见于train.py,首先定义好网络,两个生成器A2B, B2A和两个判别器A, B,以及 ...

  7. 为ASP.NET按钮(Button)添加确认对话框

    http://www.cnblogs.com/blodfox777/articles/1261303.html Button有两个点击事件: onclick 触发服务端事件,脚本为c#或VB.NET ...

  8. 出现( linker command failed with exit code 1)错误总结(http://blog.csdn.net/hengshujiyi/article/details/21182813)

    这种问题,通常出现在添加第三方库文件或者多人开发时. 这种问题一般是找不到文件而导致的链接错误. 我们可以从如下几个方面着手排查. 1.以如下错误为例,如果是多人开发,你同步完成后发现出现如下的错误. ...

  9. Java基础学习(1)

    Java基础知识 Java平台 1995年由Sun公司创建 Java的体系结构 JVM Java Virtue Machine Java代码的执行顺序 JDK Java Development Kit ...

  10. 魔咒词典 HDU - 1880 (字符串hash 单hash转int或者 双hash )

    哈利波特在魔法学校的必修课之一就是学习魔咒.据说魔法世界有100000种不同的魔咒,哈利很难全部记住,但是为了对抗强敌,他必须在危急时刻能够调用任何一个需要的魔咒,所以他需要你的帮助. 给你一部魔咒词 ...