一般通过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. Leading and Trailing LightOJ - 1282 (取数的前三位和后三位)

    题意: 求n的k次方的前三位 和 后三位 ...刚开始用 Java的大数写的...果然超时... 好吧  这题用快速幂取模求后三位  然后用一个技巧求前三位 ...orz... 任何一个数n均可以表示 ...

  2. 【AGC005F】Many Easy Problems (NTT)

    Description ​ 给你一棵\(~n~\)个点的树和一个整数\(~k~\).设为\(~S~\)为树上某些点的集合,定义\(~f(S)~\)为最小的包含\(~S~\)的联通子图的大小.\(~n~ ...

  3. A1050. String Subtraction

    Given two strings S1 and S2, S = S1 - S2 is defined to be the remaining string after taking all the ...

  4. 1093. Count PAT's

    The string APPAPT contains two PAT's as substrings. The first one is formed by the 2nd, the 4th, and ...

  5. c基础:函数参数是 struct(结构),传的是引用,还是值?

    比如函数形式:void func(struct a data1, struct b data2); 答案: 只要不是指针或者数组都是传值,其实指针也是传递的地址值. 追问但是如果这个结构体里面有数组这 ...

  6. C# 同步工作站与SQL服务器的时间

    /// <summary> /// 设置本机时间 /// </summary> public class LocalTimeSync { [DllImport("Ke ...

  7. CodeForces892E 可撤销并查集/最小生成树

    http://codeforces.com/problemset/problem/892/E 题意:给出一个 n 个点 m 条边的无向图,每条边有边权,共 Q 次询问,每次给出 ki​ 条边,问这些边 ...

  8. Elasticsearch日志分析系统

    Elasticsearch日志分析系统 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是Elasticsearch 一个采用Restful API标准的高扩展性的和高可用性 ...

  9. javascript 获取节点元素的封装

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. CodeForces - 615D Multipliers(数论)

    http://codeforces.com/problemset/problem/615/D 题意 给出m个质因子,组成一个数n.问n的约数的乘积是多少,输出mod 1e+7的结果. 分析 从输入我们 ...