学习Android已经四个月了,一直都没有写总结或者新的的习惯,有时候学习到了一些新鲜的知识也没有及时的记录下来,为了改变自己,今天就从刚学的片段管理知识讲起吧。有说错什么的,有大神看到也请指出,毕竟还是只小菜鸡。


首先从Fragment的生命周期说起,Fragment依赖于Activity,只有在Activity执行onCreate创建之后Fragment才执行onAttach、onCreate、onCreatView、onActivityCreated等方法,这些知识网上可以快速的找到,分享链接http://www.cnblogs.com/purediy/p/3276545.html,这篇文章已经很好的阐述了Fragment和Activity的联系,这里我就不多说了。我想说的是Fragment的两个比较重要的方法:onCreatView()和onDestoryView(),前者负责创建一个view显示片段内容,后者从字面上理解看似是销毁了view,其实view却并没有被销毁,view的引用还在,成员变量也还在,这跟Activity的onDestory是有区别的,既然引用还在,那么在Fragment重新onCreatView的时候就不需要再重新创建一个新的view了,成员变量也不需要重新赋值,但是如果我们直接判断if(view!=null)就returnview的话,那么就会报下面这个异常:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

这个异常告诉我们,子视图已经被关联在一个父容器里面了,我们要先对父容器调用removeView()移除掉这个view才行才行,怎么做呢?很简单,我们只需要在onDestoryView()中添加上一句代码:

@Override

public void onDestroyView() {

super.onDestroyView();

((ViewGroup)view.getParent()).removeView(view);

}

这样我们就不需要对已有的view和成员变量重新赋值,达到了一个小小优化的目的。

在这里我引用了网友分享的知识,上链接:http://www.cnblogs.com/jack-1900/p/3874228.html


紧接着另外一个问题就是Fragment切换的问题,我在开发项目过程中感觉到Fragment切换有时会伴随着卡顿现象,在网上查找资料后,按照各路大神的指点和经验,首先判断是Fragment在onCreatView初始化中做了比较长的耗时操作,于是我按照上面的优化方法,先优化了查找控件等一些初始化事件,并在Fragment的onCreatView执行开始时到onResume结束记录了总执行耗时,得到的都是100ms以上的结果,因此我想可能是片段切换的方式存在问题。


我使用的Fragment切换的方法参照的是ApiDemo的FragmentStackFragmentSupport等,Demo里面使用到的切换方法有add(),repalce(),使用回退栈来保存上一个片段状态或者返回栈中的片段状态(不知道这样描诉有没有错,或者有没有说清楚。。。具体代码大家可以看ApiDemo),例如:

Fragment newFragment = FragmentStackSupport.CountingFragment.newInstance(mStackLevel);

FragmentTransaction ft = getChildFragmentManager().beginTransaction();

ft.add(R.id.simple_fragment, newFragment).commit();----添加片段


FragmentManager fm = getChildFragmentManager();

if (fm.getBackStackEntryCount() > 0) {

fm.popBackStack(fm.getBackStackEntryAt(0).getId(),

FragmentManager.POP_BACK_STACK_INCLUSIVE);------回退到栈中某个状态

}


Fragment newFragment = FragmentStackSupport.CountingFragment.newInstance(mStackLevel);

FragmentTransaction ft = getChildFragmentManager().beginTransaction();

ft.replace(R.id.simple_fragment, newFragment);------切换片段

ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

ft.addToBackStack(null);------往栈中添加状态

ft.commit();


按照Demo的这些方法我们可以对片段进行管理,但是切换片段我们只使用add()方法网上层添加片段的话,会出现重影的问题,使用replace()替换的话就会出现现在我想要说的片段卡顿问题,不知道是不是replace()这个方法一定会出现大约100多ms的耗时操作(还不能确定大家都是不是这样)。


以上的推论只是我个人的见解,具体原因因为源代码看不到,我也不是很肯定,不过参考了网上的大神,还是让我找到了一个替代replace()的片段切换方式,那就是hide()和show();当我们使用到的片段常用不需要销毁时,我们可以使用这个方法来做,上代码:

FragmentTransaction bt = fm.beginTransaction();

if(homeFragment.isAdded()){

bt.show(homeFragment);-----如果该片段已经被添加,则显示即可;

}else{

bt.add(R.id.frame_layout, homeFragment);------如果该片段未被添加,则添加

}

bt.commit();



FragmentTransaction bt = fm.beginTransaction();-----在已经add的homeFragment上添加Fragment

bt.hide(homeFragment);---------先隐藏当前Fragment

if(myFragment.isAdded()){

bt.show(myFragment);

}else{

bt.add(R.id.frame_layout, myFragment);--------按照同样的方法显示一个片段

}

bt.commit();


通过isAdded()、show(Fragment)、add(layoutId,Fragment)这三个方法就可以取代replace()这个方法啦,耗时的操作也可以避免了。

这是引用网友知识的原址:http://www.yrom.net/blog/2013/03/10/fragment-switch-not-restart/#

大家要是看不明白我的可以去看原作写的。


就先记录到这了,这些片段替换的操作都是我们手动可控制的,如果是tabhost的话那就不太清楚了,下一个需要去研究的问题就是tabhost切换Fragment时,片段的生命周期问题。到时候再看看研究的如何。睡觉去。。。。

更多相关文章

  1. android 数据储存——--文件存储(2)
  2. android Dialog 全屏的方法
  3. 超简单的几行代码搞定Android底部导航栏功能
  4. 使用AChartEngine画柱状图
  5. Android(安卓)多 Fragment 切换优化
  6. 深入浅出Android事件分发机制——源码分析篇
  7. Android(安卓)之ActivityThead、ActivityManagerService 与activ
  8. Android(安卓)网络学习
  9. Android的Activity生命周期模拟程序及解析

随机推荐

  1. MySQL 两种恢复数据的方法
  2. MySQL 8.0 之索引跳跃扫描(Index Skip Sc
  3. mysql的登陆和退出命令格式
  4. MySql设置指定用户数据库查看查询权限
  5. MySQL group by和order by如何一起使用
  6. MySQL 8.0.19安装详细教程(windows 64位)
  7. CentOS7.5 安装MySql的教程
  8. mysql split函数用逗号分隔的实现
  9. MySQL中将一列以逗号分隔的值行转列的实
  10. MySQL将一个字段中以逗号分隔的取出来形