Fragment的常用写法
一般通过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的常用写法的更多相关文章
- 转--Android按钮单击事件的四种常用写法总结
这篇文章主要介绍了Android按钮单击事件的四种常用写法总结,比较了常见的四种写法的优劣,有不错的参考借鉴价值,需要的朋友可以参考下 很多学习Android程序设计的人都会发现每个人对代码的 ...
- 【Android】按钮点击事件的常用写法
学习总结: 最近学习了Android点击事件的常用写法.点击事件会触发监听对象身上的回调,常用写法有以下四种: 方法一:使用匿名内部类. public class MainActivity exten ...
- MyBatis 常用写法
MyBatis 常用写法 1.forEach 循环 forEach 元素的属性主要有 item, idnex, collection, open, separator, close. collec ...
- jquery常用写法简单记录
好久不写东西了......话不多说,主要记录一下,最近做的项目中用到的js的记录(虽然特别特别简单) 一 jquery常用写法记录 jQuery(this).addClass("select ...
- Android按钮单击事件的四种常用写法
这篇文章主要介绍了Android按钮单击事件的四种常用写法总结,比较了常见的四种写法的优劣,有不错的参考借鉴价值,需要的朋友可以参考下 很多学习Android程序设计的人都会发现每个人对代码的写法都有 ...
- angularjs中ng-class常用写法,三元表达式、评估表达式与对象写法
壹 ❀ 引 ng-class可以说在angularjs样式开发中使用频率特别高了,这不我想利用ng-class的三元运算符的写法来定义一个样式,结果怎么都想不起来正确写法,恼羞成怒还是整理一遍吧,那 ...
- python time和datetime常用写法格式
python 的time和datetime常用写法 import time from datetime import datetime from datetime import timedelta # ...
- mongodb java操作常用写法
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成.MongoDB 文档类似于 JSON 对象.字段值可以包含其他文档,数组及文档数组.下面介绍的是用java操作 ...
- JS中面向对象中的继承(常用写法)---核心部分
1.基本概念 子类继承父类,但是不能影响父类.包括1.混合继承(构造函数+原型) 2.ES6新增class的继承. 接下来介绍,面向对象中继承的两种常用写法.即混合继承(构造函数+原型)和class继 ...
随机推荐
- Leading and Trailing LightOJ - 1282 (取数的前三位和后三位)
题意: 求n的k次方的前三位 和 后三位 ...刚开始用 Java的大数写的...果然超时... 好吧 这题用快速幂取模求后三位 然后用一个技巧求前三位 ...orz... 任何一个数n均可以表示 ...
- 【AGC005F】Many Easy Problems (NTT)
Description 给你一棵\(~n~\)个点的树和一个整数\(~k~\).设为\(~S~\)为树上某些点的集合,定义\(~f(S)~\)为最小的包含\(~S~\)的联通子图的大小.\(~n~ ...
- A1050. String Subtraction
Given two strings S1 and S2, S = S1 - S2 is defined to be the remaining string after taking all the ...
- 1093. Count PAT's
The string APPAPT contains two PAT's as substrings. The first one is formed by the 2nd, the 4th, and ...
- c基础:函数参数是 struct(结构),传的是引用,还是值?
比如函数形式:void func(struct a data1, struct b data2); 答案: 只要不是指针或者数组都是传值,其实指针也是传递的地址值. 追问但是如果这个结构体里面有数组这 ...
- C# 同步工作站与SQL服务器的时间
/// <summary> /// 设置本机时间 /// </summary> public class LocalTimeSync { [DllImport("Ke ...
- CodeForces892E 可撤销并查集/最小生成树
http://codeforces.com/problemset/problem/892/E 题意:给出一个 n 个点 m 条边的无向图,每条边有边权,共 Q 次询问,每次给出 ki 条边,问这些边 ...
- Elasticsearch日志分析系统
Elasticsearch日志分析系统 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是Elasticsearch 一个采用Restful API标准的高扩展性的和高可用性 ...
- javascript 获取节点元素的封装
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- CodeForces - 615D Multipliers(数论)
http://codeforces.com/problemset/problem/615/D 题意 给出m个质因子,组成一个数n.问n的约数的乘积是多少,输出mod 1e+7的结果. 分析 从输入我们 ...