android之Fragment的bug解决

最近做一个功能,当第二次进入一个界面的时候出现一个奇怪的bug,如下面详细的log信息:

10-01 13:36:23.549: E/AndroidRuntime(14188): Process: com.android.settings, PID: 14188
10-01 13:36:23.549: E/AndroidRuntime(14188): android.view.InflateException: Binary XML file line #43: Error inflating class fragment
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at com.android.settings.accessibility.ToggleCaptioningPreferenceFragment.onCreateView(ToggleCaptioningPreferenceFragment.java:69)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.app.Fragment.performCreateView(Fragment.java:1700)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:890)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.app.BackStackRecord.run(BackStackRecord.java:698)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1447)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.os.Handler.handleCallback(Handler.java:808)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.os.Handler.dispatchMessage(Handler.java:103)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.os.Looper.loop(Looper.java:193)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.app.ActivityThread.main(ActivityThread.java:5333)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at java.lang.reflect.Method.invokeNative(Native Method)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at java.lang.reflect.Method.invoke(Method.java:515)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at dalvik.system.NativeStart.main(Native Method)
10-01 13:36:23.549: E/AndroidRuntime(14188): Caused by: java.lang.IllegalArgumentException: Binary XML file line #43: Duplicate id 0x7f0b0034, tag null, or parent id 0xffffffff with another fragment for com.android.settings.accessibility.CaptionPropertiesFragment
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.app.Activity.onCreateView(Activity.java:4912)
10-01 13:36:23.549: E/AndroidRuntime(14188): 	at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689)

如上的log信息可以知道:加载了一个(Duplicate)重复的Fragment(CaptionPropertiesFragment)。问题是代码应该是没有问题的!具体看看我系的代码:

public class ToggleCaptioningPreferenceFragment extends Fragment {
    private static final float DEFAULT_FONT_SIZE = 48f;

    private CaptionPropertiesFragment mPropsFragment;
    private SubtitleView mPreviewText;
    private CaptioningManager mCaptioningManager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mCaptioningManager = (CaptioningManager) getActivity()
                .getSystemService(Context.CAPTIONING_SERVICE);
    }

    @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        final View rootView = inflater.inflate(R.layout.captioning_preview, container, false);

        // We have to do this now because PreferenceFrameLayout looks at it
        // only when the view is added.
        if (container instanceof PreferenceFrameLayout) {
            ((PreferenceFrameLayout.LayoutParams) rootView.getLayoutParams()).removeBorders = true;
        }

        return rootView;
    }

从报错信息可以知道出错的代码:final View rootView = inflater.inflate(R.layout.captioning_preview, container, false);

那么报错信息说是加载了重复的Fragment(CaptionPropertiesFragment)。实际上这个重复的Fragment在这个layout文件里面布局的:R.layout.captioning_preview。

很显然,就是第一次进入这个界面,再退出的时候,这个用过的Fragment(CaptionPropertiesFragment)没有remove掉!从而出现了两个问题:

(1)为什么会出现这个Fragment(CaptionPropertiesFragment)没有remove,

(2)怎么解决这个问题!

在activity中不同的frament之间项目替换的时候,FragmentManager只会remove和add这些frament,然而这些frament里面自己加载的frament(这里就是我们的CaptionPropertiesFragment)是没有被remove. 很显然这是一个缺陷!因为后一个frament(CaptionPropertiesFragment)很明显是依赖与他的父frament的,应该同时递归的remove.

那么如何解决这个问题呢!很显然就是在不用这个frament(ToggleCaptioningPreferenceFragment)的时候把他里面加载的frament给remove掉!这个操作在ToggleCaptioningPreferenceFragment的onDestroyView()里面就可以解决问题了!如下代码:

	@Override
	public void onDestroyView() {
		super.onDestroyView();

	 	if(mPropsFragment != null){
			FragmentManager f = getFragmentManager();
			if(f != null && !f.isDestroyed()){
				final FragmentTransaction ft = f.beginTransaction();
				if(ft != null){
					ft.remove(mPropsFragment).commit();
				}
			}
	 	}
	}

这里要注意f.isDestroyed()这样来判断是否这个FragmentManager处于Destroyed,如果不加这个判断的话,横竖屏切换时候会出错!

注意:对于这个问题,网上有各种无效的解决办法。

时间: 2024-10-17 20:33:25

android之Fragment的bug解决的相关文章

(原创)优酷android客户端 下载中 bug 解决

在网络情况不好的情况下,优酷android客户端下载视频会终止,用户放弃下载点击 删除该任务以后,切换到网络好的情况下进行下载,会显示该视频已在下载队列里,然后客户端UI界面却什么都看不到.导致用户根本无法下载. 其实优酷的下载都是使用读文件形式的 在优酷android的文件目录那里,(目前不考虑挂在SD卡和其他存储优化)就是内存设备/youku/offinedata里有很多下载视频的文件夹,里面有文件夹创建的时间.图片.flv形式的分集.info文件.youku.m3u8文件 下载信息(包括下

Android使用Fragment,不能得到Fragment内部控件,findViewById()结果是Null--已经解决

大家在登录网站的时候,大部分时候是通过一个表单提交登录信息.但是有时候浏览器会弹出一个登录验证的对话框,如下图,这就是使用HTTP基本认证.下面来看看一看这个认证的工作过程:第一步:  客户端发送http request 给服务器,服务器验证该用户是否已经登录验证过了,如果没有的话,服务器会返回一个401 Unauthozied给客户端,并且在Response 的 header "WWW-Authenticate" 中添加信息.如下图.第二步:浏览器在接受到401 Unauthozie

Android较低版本(<5.2) 页面默认Select选择框效果的BUG解决

Bug描述: 使用低版本安卓(<5.2),在微信上打开网页,点击下拉框,会出现如下图所示的用来展示select选项的弹出框: 在选项较少的时候,可以向下滑动,将选项滑到底部 滑动前: 滑动后: 期望达到的效果: 解决方案: 判断是否是微信环境: function isWeixinBrowser(){ return /micromessenger/.test(navigator.userAgent.toLowerCase()); } 判断安卓版号: var userAgent = navigato

android viewpager fragment切换时界面卡顿解决办法

目前开发的程序在切换View时界面卡顿现象比较严重,影响用户体验,当前项目共就四个View,每个View也只是按钮,所以可以同时加载,不让其它view销毁. 只需在Adapter中重载destroyItem类即可 @Override public void destroyItem(ViewGroup container, int position, Object object) { //重载该方法,防止其它视图被销毁,防止加载视图卡顿 //super.destroyItem(container,

转-android.app.Fragment$InstantiationException 解决办法

在实际的开发中,我遇到过两次android.app.Fragment$InstantiationException报错. 其中一次报错,根据报错提示 “make sure class name exists, is public, and has an empty constructor that is public” ,若Fragement定义有带参构造函数,则一定要定义public的默认的构造函数.即可解决此问题.如果硬要携带参数进去,可以通过Intent结合Bunble的方式携带进去. 第

Android中Fragment的使用

Fragment可能是我心中一直以来的执念,由于Android开发并没有像一般流程一样系统的学习,而是直接在公司项目中改bug开始的.当时正是Fragment被提出来的时候,那时把全部精力放到了梳理代码业务逻辑上,错过了Fragment首班车,而这一等就到现在. Android发布的前两个版本只适配小尺寸的手机.开发适配小尺寸手机app只需要考虑怎么将控件布局到Activity中,怎样打开一个新的Activity等就可以了.然而Android3.0开始支持平板,屏幕尺寸增大到10寸.这在很大程度

android之Fragment基础详解(一)

一.Fragment的设计哲学 Android在3.0中引入了fragments的概念,主要目的是用在大屏幕设备上--例如平板电脑上,支持更加动态和灵活的UI设计.平板电脑的屏幕比手机的大得多,有更多的空间来放更多的UI组件,并且这些组件之间会产生更多的交互. 针对屏幕尺寸的差距,很多情况下,都是先针对手机开发一套App,然后拷贝一份,修改布局以适应平板神马超级大屏的.难道无法做到一个App可以同时适应手机和平板么,当然了,必须有啊.Fragment的出现就是为了解决这样的问题.你可以把Frag

Android ViewPager Fragment使用懒加载提升性能

?? Android ViewPager Fragment使用懒加载提升性能 Fragment在如今的Android开发中越来越普遍,但是当ViewPager结合Fragment时候,由于Android ViewPager内在的加载机制,导致一个比较严重的加载性能问题,具体来说,假设一个ViewPager中有n多个Fragment,那么ViewPager在初始化阶段将一次性的初始化FragmentPagerAdapter中的至少3个Fragment(如果Fragment多于3),创建和加载Fra

[转]Android:Activity+Fragment及它们之间的数据交换(一)

2014-05-18         来源:Android:Activity+Fragment及它们之间的数据交换(一)   简介: 为什么要用Fragment?使用Fragment可以在一个Activity中实现不同的界面.Fragment与 Fragment之间的动画切换,远比Activity与Activity之间的动画切换变化方式多.很多时候,我们通过使用一个Activity,切换 多个Fragment.本次博客,主要列举一下Fragment与它的Activity之间进行数据交换的方式.