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继 ...
随机推荐
- Uva10474-STL水题-白书
白书的一道水题.话说好久没认真做难题了.今天出了排名,所有队伍里倒数第一啊! 代码没什么可说的了. #include <algorithm> #include <cstring> ...
- Hibernate基本应用01
一. Hibernate简介 1.1 Hibernate介绍 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全 ...
- String类型的特殊之处
String是一种特殊的引用类型,那么它究竟特殊在哪里? 请看看下面这个程序,输出什么结果? public static void changeStr(String str) { str = &quo ...
- suoi21 高能显示屏 (cdq分治)
可以把翻倍的操作看作是一个查询和修改(增加刚查询得来的值)的符合操作,然后做cdq就行了 #include<bits/stdc++.h> #define pa pair<int,in ...
- .net连接ORACLE数据库
这段时间维护客户的一个系统,该系统使用的是ORACLE数据库,之前开发的时候用的都是MSSQL,并没有使用过ORACLE.这两种数据库虽然都是关系型数据库,但是具体的操作大有不同,这里作下记录. 连接 ...
- Android -- 面试 -- 数据库升级策略
升级:重写onUpgrade方法 确定 相邻版本 的差别,从版本1开始依次迭代更新,先执行v1到v2,再v2到v3…… 为 每个版本 确定与现在数据库的差别,为每个case撰写专门的升级代码. 降级 ...
- Linux 常用命令——cat, tac, nl, more, less, head, tail, od
Drecik学习经验分享 转载请注明出处:http://blog.csdn.net/drecik__/article/details/8453584 1. cat 由第一行开始显示文件内容 2. ta ...
- C++ 中的导致编译错误汇总
多少年来,各路英雄好汉,八方神犇大佬,在CE中饮恨退役. OI的CE,还是那样熟悉的味道. (博主只能想到这么多,欢迎大家来补充) 1.变量名和内置函数冲突?!?! C++内置函数很多很多,许多你不知 ...
- 【洛谷P2384】最短乘积路径
题目大意:给定 N 个点,M 条边的有向图,边有边权,求从 1 号顶点到 N 号顶点的最短乘积路径.(经过的路径乘积最小)结果对9987取模. 乘积会爆 long long ,同时由于 dij 算法的 ...
- python post提交
# coding:utf8 import requests def login(): url = 'http://back.xiyilang.cc/staff/login.json' headers= ...