【Android】保存Fragment切换状态
前言
一般频繁切换Fragment会导致频繁的释放和创建,如果Fragment比较臃肿体验就非常不好了,这里分享一个方法。
声明
欢迎转载,但请保留文章原始出处:)
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com
正文
一、应用场景
1、不使用ViewPager
2、不能用replace来切换Fragment,会导致Fragment释放(调用onDestroyView)
二、实现
1、xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1.0" >
</FrameLayout> <RadioGroup
android:id="@+id/main_radio"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:gravity="bottom"
android:layout_marginBottom="-6dp"
android:orientation="horizontal" > <RadioButton
android:id="@+id/radio_button0"
style="@style/main_tab_bottom"
android:drawableTop="@drawable/bottom_1" /> <RadioButton
android:id="@+id/radio_button1"
style="@style/main_tab_bottom"
android:drawableTop="@drawable/bottom_2" /> <RadioButton
android:id="@+id/radio_button2"
style="@style/main_tab_bottom"
android:drawableTop="@drawable/bottom_3" /> <RadioButton
android:id="@+id/radio_button3"
style="@style/main_tab_bottom"
android:drawableTop="@drawable/bottom_4" /> <RadioButton
android:id="@+id/radio_button4"
style="@style/main_tab_bottom"
android:drawableTop="@drawable/bottom_5" />
</RadioGroup> </LinearLayout>
代码说明:
非常常见的底部放5个RadioButton,点击切换不同的Fragment。
2、Activity
为RadioButton设置setOnCheckedChangeListener事件,其他代码:
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Fragment fragment = (Fragment) mFragmentPagerAdapter.instantiateItem(mContainer, buttonView.getId());
mFragmentPagerAdapter.setPrimaryItem(mContainer, 0, fragment);
mFragmentPagerAdapter.finishUpdate(mContainer);
}
} private FragmentPagerAdapter mFragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) { @Override
public Fragment getItem(int position) {
switch (position) {
case R.id.radio_button1:
return new Fragment1();
case R.id.radio_button2:
return new Fragment2();
case R.id.radio_button3:
return new Fragment3();
case R.id.radio_button4:
return new Fragment4();
case R.id.radio_button0:
default:
return new Fragment0();
}
} @Override
public int getCount() {
return 5;
}
};
代码说明:
instantiateItem从FragmentManager中查找Fragment,找不到就getItem新建一个,setPrimaryItem设置隐藏和显示,最后finishUpdate提交事务。
mContainer就是xml中的FrameLayout。
三、FragmentPagerAdapter核心代码
@Override
public Object instantiateItem(ViewGroup container, int position) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
} final long itemId = getItemId(position); // Do we already have this fragment?
String name = makeFragmentName(container.getId(), itemId);
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
mCurTransaction.attach(fragment);
} else {
fragment = getItem(position);
if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
mCurTransaction.add(container.getId(), fragment,
makeFragmentName(container.getId(), itemId));
}
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
} return fragment;
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
+ " v=" + ((Fragment)object).getView());
mCurTransaction.detach((Fragment)object);
} @Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (fragment != mCurrentPrimaryItem) {
if (mCurrentPrimaryItem != null) {
mCurrentPrimaryItem.setMenuVisibility(false);
mCurrentPrimaryItem.setUserVisibleHint(false);
}
if (fragment != null) {
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
}
mCurrentPrimaryItem = fragment;
}
} @Override
public void finishUpdate(ViewGroup container) {
if (mCurTransaction != null) {
mCurTransaction.commitAllowingStateLoss();
mCurTransaction = null;
mFragmentManager.executePendingTransactions();
}
}
FragmentPagerAdapter是support包自带的类。
四、注意
之前自己模拟ViewPager用attach、setMenuVisibility、setUserVisibleHint来控制Fragment的显示隐藏,经常会出现Fragment重叠现象,非常头疼,换了这个之后目前没有发现重叠现象。
五、文章后期维护
2013-12-01 上传示例代码:http://files.cnblogs.com/over140/SampleFragmentSwitch.zip
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if (this.getView() != null)
this.getView().setVisibility(menuVisible ? View.VISIBLE : View.GONE);
}
重新做例子时发现自己也出不来效果了,后来发现少了这段代码。
2014-01-08 想实现本文的效果还是推荐直接使用ViewPager,通过自定义ViewPager禁用掉左右滑动和自动销毁即可,根据评论来看非正常情况下重影现象还是挺严重的。
结束
需要多看看源码,才能很好的解决问题。
【Android】保存Fragment切换状态的更多相关文章
- Android使得Fragment 切换时不重新实例化
以前实现Fragment的切换都是用replace方法实现 public void startFragmentAdd(Fragment fragment) { FragmentManager frag ...
- android viewpager fragment切换时界面卡顿解决办法
目前开发的程序在切换View时界面卡顿现象比较严重,影响用户体验,当前项目共就四个View,每个View也只是按钮,所以可以同时加载,不让其它view销毁. 只需在Adapter中重载destroyI ...
- Android下fragment切换的动画效果
网上看到的例子,转过来记录一下,学习一下,感谢原作者的辛勤编码,效果非常好 基于Android3.0新增的动画api,效果很赞 共21种动画效果: <item>X轴缩放</item& ...
- Android中Fragment+ViewPager的配合使用
官方推荐 ViewPager与Fragment一起使用,可以更加方便的管理每个Page的生命周期,这里有标准的适配器实现用于ViewPager和Fragment,涵盖最常见的用例.FragmentPa ...
- Android 进阶 Fragment 介绍和使用 (二)
管理fragment 因为FragmentManager的API是在Android 3.0,也即API level 11开始引入的,所以对于之前的版本,需要使用support library中的Fra ...
- Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3364728.html 我前两天写过一篇博客<Android使用Fragment来 ...
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3360938.html 如新浪微博下面的标签切换功能,我以前也写过一篇博文(http:/ ...
- android fragment+ FragmentTabHost+viewpager 切换状态不保存的问题
转载请注明出处:http://blog.csdn.net/djy1992/article/details/46674169 @author dujinyang 难得有时间上来写博客. fragment ...
- 保存和恢复 Android Fragment 的状态
经过几年在 Android 应用开发中应用 Fragment 的努力之后,我必须要说尽管Fragment的概念非常优秀,但是它也同时带来了一堆问题.当我们处理实例的状态保存时就需要特别一件一件地修护好 ...
随机推荐
- 相同版本的CDH集群间迁移hdfs以及hbase
前言 由于项目数据安全的需要,这段时间看了下hadoop的distcp的命令使用,不断的纠结的问度娘,度娘告诉我的结果也让我很纠结,都是抄来抄去, 还好在牺牲大量的时间的基础上还终于搞出来了,顺便写这 ...
- NET RichTextBox控件如何可以插入图像
本文介绍.NET RichTextBox控件如何可以插入图像,控制和ActiveX对象通过使用OLE方式,如在解释,.不幸的是,它涵盖了只用一个C源代码样本,所以我需要在托管代码(C#)实施类似的解决 ...
- The service cannot be activated because it does not support ASP.NET compatibility
刚刚在ASP.NET创建一个Service,在运行时,它即显示异常: The service cannot be activated because it does not support ASP.N ...
- MVP的PV模式与SC模式
MVC是现今挺被推崇的一种架构模式,而MVP在MVC的基础对视图与模型上再解耦,使结构和各自的功能也有所改变.在去年鄙人也尝试了一下使用MVP做了一个小Demo,作为了MVC的一个变体,MVP还分了两 ...
- 电脑Windows使用中遇到的那些问题
Win64位注册表导入方法 64位Windows操作系统注册表不同于32位Windows操作系统,Win64 位版本分为 32 位注册表项和 64 位注册表项.默认 64 位版本注册表编辑器 (Reg ...
- MVC之前的那点事儿系列(3):HttpRuntime详解分析(下)
文章内容 话说,经过各种各样复杂的我们不知道的内部处理,非托管代码正式开始调用ISPAIRuntime的ProcessRequest方法了(ISPAIRuntime继承了IISPAIRuntime接口 ...
- Ubuntu密码错误的问题
安装了一个Ubuntu,启动以后进入终端,想su root,提示输入密码,输入了很多次密码(我的用户密码和root密码是一样的),总是Login incorrect. 后来输入了用户名,提示输入密码, ...
- python signal(信号)
信号的概念 信号(signal)-- 进程之间通讯的方式,是一种软件中断.一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号. 几个常用信号: SIGINT 终止进程 中断进 ...
- No.013:Roman to Integer
问题: Given a roman numeral, convert it to an integer.Input is guaranteed to be within the range from ...
- CodeBlock
CodeBlock官网是: http://www.codeblocks.org/ 选择Download the binary release: 根据自己电脑的情况选择想要的版本:(以博主电脑为例,wi ...