一般通过add、show、hide相结合的方法来控制Fragment的显示和隐藏,这样不会再重写一遍Fragment的生命周期,节省了时间和内存,当然特殊需求除外。

package com.example.lzp;

import android.os.PersistableBundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.RadioGroup; public class MainActivity extends FragmentActivity implements RadioGroup.OnCheckedChangeListener{ // 负责全局的FragmentManager, 建议使用support包中的FramengManager类
private FragmentManager fm;
private Fragment oneFragment, twoFragment, threeFragment; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); fm = getSupportFragmentManager();
RadioGroup tabRadio = (RadioGroup) findViewById(R.id.tab_radio);
tabRadio.setOnCheckedChangeListener(this);
if (oneFragment == null){
oneFragment = new OneFragment();
}
fm.beginTransaction().add(R.id.fragment_container, oneFragment).commit();
} @Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
FragmentTransaction transaction = fm.beginTransaction();
switch (checkedId){
case R.id.one:
// 判断是否为空
if (oneFragment == null){
oneFragment = new OneFragment();
}
// 判断是否添加这个fragment对象是否已经添加到容器中
// 如果已经添加过了,就show,如果没有添加就add
if (oneFragment.isAdded()){
transaction.show(oneFragment);
}else{
transaction.add(R.id.fragment_container,oneFragment);
}
// 隐藏掉其他的两个fragment
if (twoFragment != null && twoFragment.isAdded()){
transaction.hide(twoFragment);
}
if (threeFragment != null && threeFragment.isAdded()){
transaction.hide(threeFragment);
}
break; case R.id.two:
// 判断是否为空
if (twoFragment == null){
twoFragment = new TwoFragment();
}
// 判断是否添加这个fragment对象是否已经添加到容器中
// 如果已经添加过了,就show,如果没有添加就add
if (twoFragment.isAdded()){
transaction.show(twoFragment);
}else{
transaction.add(R.id.fragment_container,twoFragment);
}
// 隐藏掉其他的两个fragment
if (oneFragment != null && oneFragment.isAdded()){
transaction.hide(oneFragment);
}
if (threeFragment != null && threeFragment.isAdded()){
transaction.hide(threeFragment);
}
break;
case R.id.three:
// 判断是否为空
if (threeFragment == null){
threeFragment = new ThreeFragment();
}
// 判断是否添加这个fragment对象是否已经添加到容器中
// 如果已经添加过了,就show,如果没有添加就add
if (threeFragment.isAdded()){
transaction.show(threeFragment);
}else{
transaction.add(R.id.fragment_container,threeFragment);
}
// 隐藏掉其他的两个fragment
if (twoFragment != null && twoFragment.isAdded()){
transaction.hide(twoFragment);
}
if (oneFragment != null && oneFragment.isAdded()){
transaction.hide(oneFragment);
}
break;
default:
break;
}
transaction.commitAllowingStateLoss();
} @Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
}
}

很多初学的开发者认为写出上面的代码就可以了。实际上在功能是没有问题的,但是却有一个隐藏的巨大bug,假如MainActivity被回收,那也就说明MainActivity中所有的对象都被回收了,包括之前创建过的三个fragment,下次回到MainActivity的时候还会再创建一遍,判断是否已经添加过还是返回false,这样的情况出现多次,容器中就会添加了很多的同一类型的fragnment,最终出现内存溢出。
解决办法1: 
借助Activity的onSaveInstanceState()

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if (savedInstanceState != null){
//obj = savedInstanceState.getSerializable(key);
obj = savedInstanceState.getParcelableArray(key);
} ......
} @Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
//outState.putSerializable(key, obj);
outState.putParcelable(key, obj);
}

这个方法会在activi回收的时候回调,可以重写这个方法保存一些我们想保存的信息,view的状态信息一般已经被自动保存了,不需要我们特意去写(实际测试锤子和坚果手机除外)。上面两个方法帮助我们保存对象,这个类必须实现可序列化接口,android系统推荐的是使用第二个方法--Parcelable。下次回到Activity的时候去判断是否有保存的信息,取出之前保存的对象即可。

解决办法2:

通过给fragment设置标签来保证容器中只有同一个类型的对象

transaction.add(R.id.fragment_container,oneFragment, "oneFragment");

add方法中的第三个参数就是我们设置的标签,同一个类型我们设置一个唯一的标签,切换的时候通过标签获取对象:

FragmentManager fm = getSupportFragmentManager();
oneFragment = fm.findFragmentByTag("oneFragment");
if(oneFragment == null){
oneFragment = new OneFragment();
}...

下面贴出第二种方法的完整代码:

package com.example.lzp;

import android.os.PersistableBundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.RadioGroup; public class MainActivity extends FragmentActivity implements RadioGroup.OnCheckedChangeListener{ // 负责全局的FragmentManager, 建议使用support包中的FramengManager类
private FragmentManager fm;
private Fragment oneFragment, twoFragment, threeFragment; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); fm = getSupportFragmentManager();
RadioGroup tabRadio = (RadioGroup) findViewById(R.id.tab_radio);
tabRadio.setOnCheckedChangeListener(this);
// 如果不需要恢复之前的状态,默认显示的是第一个oneFragment
if (savedInstanceState == null){
if (oneFragment == null){
oneFragment = new OneFragment();
}
fm.beginTransaction().add(R.id.fragment_container, oneFragment).commit();
} } @Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
FragmentTransaction transaction = fm.beginTransaction();
switch (checkedId){
case R.id.one:
// 从容器通过标签获取相同类型的Fragment
oneFragment = fm.findFragmentByTag("OneFragment");
// 判断是否为空
if (oneFragment == null){
oneFragment = new OneFragment();
}
// 判断是否添加这个fragment对象是否已经添加到容器中
// 如果已经添加过了,就show,如果没有添加就add
if (oneFragment.isAdded()){
transaction.show(oneFragment);
}else{
transaction.add(R.id.fragment_container,oneFragment, "OneFragment");
}
// 隐藏掉其他的两个fragment
if (twoFragment != null && twoFragment.isAdded()){
transaction.hide(twoFragment);
}
if (threeFragment != null && threeFragment.isAdded()){
transaction.hide(threeFragment);
}
break; case R.id.two:
// 从容器通过标签获取相同类型的Fragment
twoFragment = fm.findFragmentByTag("TwoFragment");
// 判断是否为空
if (twoFragment == null){
twoFragment = new TwoFragment();
}
// 判断是否添加这个fragment对象是否已经添加到容器中
// 如果已经添加过了,就show,如果没有添加就add
if (twoFragment.isAdded()){
transaction.show(twoFragment);
}else{
transaction.add(R.id.fragment_container,twoFragment, "TwoFragment");
}
// 隐藏掉其他的两个fragment
if (oneFragment != null && oneFragment.isAdded()){
transaction.hide(oneFragment);
}
if (threeFragment != null && threeFragment.isAdded()){
transaction.hide(threeFragment);
}
break;
case R.id.three:
// 从容器通过标签获取相同类型的Fragment
threeFragment = fm.findFragmentByTag("ThreeFragment");
// 判断是否为空
if (threeFragment == null){
threeFragment = new ThreeFragment();
}
// 判断是否添加这个fragment对象是否已经添加到容器中
// 如果已经添加过了,就show,如果没有添加就add
if (threeFragment.isAdded()){
transaction.show(threeFragment);
}else{
transaction.add(R.id.fragment_container,threeFragment);
}
// 隐藏掉其他的两个fragment
if (twoFragment != null && twoFragment.isAdded()){
transaction.hide(twoFragment);
}
if (oneFragment != null && oneFragment.isAdded()){
transaction.hide(oneFragment);
}
break;
default:
break;
}
transaction.commitAllowingStateLoss();
} }

http://blog.csdn.net/u011315960/article/details/51192635

Fragment的常用写法的更多相关文章

  1. 转--Android按钮单击事件的四种常用写法总结

    这篇文章主要介绍了Android按钮单击事件的四种常用写法总结,比较了常见的四种写法的优劣,有不错的参考借鉴价值,需要的朋友可以参考下     很多学习Android程序设计的人都会发现每个人对代码的 ...

  2. 【Android】按钮点击事件的常用写法

    学习总结: 最近学习了Android点击事件的常用写法.点击事件会触发监听对象身上的回调,常用写法有以下四种: 方法一:使用匿名内部类. public class MainActivity exten ...

  3. MyBatis 常用写法

    MyBatis 常用写法 1.forEach 循环   forEach 元素的属性主要有 item, idnex, collection, open, separator, close. collec ...

  4. jquery常用写法简单记录

    好久不写东西了......话不多说,主要记录一下,最近做的项目中用到的js的记录(虽然特别特别简单) 一 jquery常用写法记录 jQuery(this).addClass("select ...

  5. Android按钮单击事件的四种常用写法

    这篇文章主要介绍了Android按钮单击事件的四种常用写法总结,比较了常见的四种写法的优劣,有不错的参考借鉴价值,需要的朋友可以参考下 很多学习Android程序设计的人都会发现每个人对代码的写法都有 ...

  6. angularjs中ng-class常用写法,三元表达式、评估表达式与对象写法

     壹 ❀ 引 ng-class可以说在angularjs样式开发中使用频率特别高了,这不我想利用ng-class的三元运算符的写法来定义一个样式,结果怎么都想不起来正确写法,恼羞成怒还是整理一遍吧,那 ...

  7. python time和datetime常用写法格式

    python 的time和datetime常用写法 import time from datetime import datetime from datetime import timedelta # ...

  8. mongodb java操作常用写法

    MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成.MongoDB 文档类似于 JSON 对象.字段值可以包含其他文档,数组及文档数组.下面介绍的是用java操作 ...

  9. JS中面向对象中的继承(常用写法)---核心部分

    1.基本概念 子类继承父类,但是不能影响父类.包括1.混合继承(构造函数+原型) 2.ES6新增class的继承. 接下来介绍,面向对象中继承的两种常用写法.即混合继承(构造函数+原型)和class继 ...

随机推荐

  1. SQL partition (小组排序)

    很多时候,我们在SQL中进行数据去重(distinct) 结果发现有2条一样ID,或者name的数据,我们想要最接近的那条数据. 直接看看题目: 原表 select ID,Title,PRICE fr ...

  2. MyBatis在表名作为参数时遇到的问题

    之前在用MyBatis的时候没用过表名作为参数,最近使用到了. 基于注释使用MyBatis的Dao层代码如下: @Repository public interface Base1102Dao { @ ...

  3. Mayor's posters POJ - 2528(线段树 + 离散化)

    Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 74745   Accepted: 21574 ...

  4. tmux的使用

    tmux的使用 1: tmux的介绍     tmux是一个优秀的终端多路复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权.使用它最直观的好处就是,通过一个终端登录远程主机并 ...

  5. MT【220】三次方程必有实根

    设$f(x)=x^2+ax+b,g(x)=x^2+cx+d$,如果$f(g(x))=g(f(x))$没有实根,求证:$b\ne d$ 分析:$f(g(x))-g(f(x))=2(c-a)x^3+\cd ...

  6. MT【214】焦点弦长公式

    已知椭圆焦点为$F_1(-1,0),F_2(1,0)$,且椭圆与直线$y=x-\sqrt{3}$相切,求(1)椭圆的方程(2)过$F_1$作两条相互垂直的直线$l_1,l_2$与椭圆相交于$P,Q,M ...

  7. Hdoj 1009.FatMouse' Trade 题解

    Problem Description FatMouse prepared M pounds of cat food, ready to trade with the cats guarding th ...

  8. 洛谷 P2466 Sue的小球 解题报告

    P2466 [SDOI2008]Sue的小球 题目描述 Sue和Sandy最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺激的大海上,Sue有一支轻便小巧的小船.然而,Sue的目标并不是当 ...

  9. Android Selector 与 Shape 基本用法

    分类: Android2011-07-19 11:07 7513人阅读 评论(4) 收藏 举报 androidencodingbutton测试c 1:Selector drawable的item中可以 ...

  10. Unity3d-AngryBots实例解读

    最近粗略研究了下Unity3d自带的例子AngryBots,记录一下,部分内容摘自http://oulehui.blog.163.com/blog/static/7961469820125251051 ...