编写原生看书页面 轮播图模块时遇到的fragment问题

书籍页面需要显示轮播图组件,上网找了个现成封装好的,感谢这个哥们儿 http://blog.csdn.net/stevenhu_223/article/details/45577781

down下来用到看书中,是封装在fragment里的,我是在BookView中动态调用的,调用方式:

LayoutInflater lif = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View lubotuView = lif.inflate(R.layout.lunbotu, null);
CycleViewPager cycleViewPager = (CycleViewPager) ((Activity) context).getFragmentManager().findFragmentById(R.id.lunbotuCycle);
LinearLayout lunbotuLL = (LinearLayout) lubotuView.findViewById(R.id.lunbotuLL);
addView(lubotuView);

好使,成功调用。

但是在翻页过程中,第二次翻到此页就崩溃了,崩溃信息:

E/AndroidRuntime(6462): android.view.InflateException: Binary XML file line #8: Error inflating class fragment
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:719)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.view.LayoutInflater.rInflate(LayoutInflater.java:761)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.view.LayoutInflater.inflate(LayoutInflater.java:498)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at com.sea.testRatingBar.bookView.loadCarouselNode(bookView.java:132)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at com.sea.testRatingBar.bookView.loadElement(bookView.java:63)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at com.sea.testRatingBar.bookView.<init>(bookView.java:50)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at com.sea.testRatingBar.BookPageAdapter.getView(BookPageAdapter.java:55)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at com.aphidmobile.flip.FlipViewController.viewFromAdapter(FlipViewController.java:478)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at com.aphidmobile.flip.FlipViewController.flippedToView(FlipViewController.java:545)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at com.aphidmobile.flip.FlipViewController$2.run(FlipViewController.java:519)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.os.Handler.handleCallback(Handler.java:733)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.os.Handler.dispatchMessage(Handler.java:95)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.os.Looper.loop(Looper.java:136)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.app.ActivityThread.main(ActivityThread.java:5479)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at java.lang.reflect.Method.invokeNative(Native Method)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at java.lang.reflect.Method.invoke(Method.java:515)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at dalvik.system.NativeStart.main(Native Method)
10-14 06:51:37.676: E/AndroidRuntime(6462): Caused by: java.lang.IllegalArgumentException: Binary XML file line #8: Duplicate id 0x7f09000a, tag null, or parent id 0x7f090009 with another fragment for cn.androiddevelop.cycleviewpager.lib.CycleViewPager
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.app.Activity.onCreateView(Activity.java:5002)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:695)
10-14 06:51:37.676: E/AndroidRuntime(6462): 	... 20 more

一看就是fragment重复调用,造成了这个错误

解决方案1:所以用完了得remove掉,在CycleViewPager这个fragment中添加个ondestroy方法,当ondestroy销毁时remove此frg

public void onDestroyView() {
	    super.onDestroyView();
	    FragmentManager fm = getActivity().getSupportFragmentManager();
	    Fragment fragment = (fm.findFragmentById(R.id.cyclepic));
	    FragmentTransaction ft = fm.beginTransaction();
	    ft.remove(fragment);
	    ft.commit();
	}

测试,不好使,Sh*t 

解决方案2:优化oncreate生命周期,如果之前创建过,就删除,老一套:

<span style="white-space:pre">	</span>public CycleViewPager() {
	}

	private static View rootView;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		// View view =
		// LayoutInflater.from(getActivity()).inflate(R.layout.view_cycle_viewpager_contet,
		// null);
		if (rootView != null) {
			ViewGroup parent = (ViewGroup) rootView.getParent();
			if (parent != null)
				parent.removeView(rootView);
		}
		try {
			rootView = LayoutInflater.from(getActivity()).inflate(R.layout.view_cycle_viewpager_contet, null);
		} catch (InflateException e) {
		}
测试,不好使,double Sh*t

解决方案3:这些都不好使,那还试试那个remove的,经过了漫长的逻辑方面的探索,终于锁定在adapter中,移除所有view之前remove

int childCount0 = viewHolder.ll.getChildCount();
for (int i = 0; i < childCount0; i++) {
	View v = viewHolder.ll.getChildAt(i);
	BookView bv = (BookView) v;
	int bvChildCount = bv.getChildCount();
	for (int j = 0; j < bvChildCount; j++) {
		View bvv = bv.getChildAt(j);
		if(bvv instanceof LinearLayout){
			if(bvv.getId() == R.id.lunbotuLL){
				FragmentManager fm = ((Activity) c).getFragmentManager();
				Fragment fragment = fm.findFragmentById(R.id.lunbotuCycle);
				FragmentTransaction ft = fm.beginTransaction();
				ft.remove(fragment);
				ft.commit();
			}
		}
	}
}
viewHolder.ll.removeAllViews();
测试,还tm不好使,triple Sh*t 

解决方法4:思考了一下,逻辑肯定是对的,还是报错的话,是不是ft.commit这个方法不执行啊,

上网搜到了一篇文章http://blog.csdn.net/picasso_l/article/details/50994143 ,按照文章说法,添加了一个

fm.executePendingTransactions();
即 立即执行 !

测试,好使!





贴一下http://blog.csdn.net/picasso_l/article/details/50994143 这个博客的内容,当做记录,对博主表示感谢:

FragmentTransaction是异步的,commit()仅是相当于把操作加入到FragmentManager的队列,然后FragmentManager会在某一个时刻来执行,并不是立即执行。所以,真正开始执行commit()时,如果Activity的生命周期发生了变化,比如走到了onPause,或者走到了onStop,或者onDestroy都走完了,那么就会报出IllegalStateException。

这个地方确实是很坑的,我在做一个功能,需要从FragmentA跳转到FragmentB,然后调用FragmentB的刷新方法,那我的思路是从FragmentA和B的MainActivity中将A隐藏,将B显示,然后调用刷新。 
于是我先将A隐藏B显示

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">private void switchFragment(Fragment newFragment) {

        FragmentManager fm = getSupportFragmentManager()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        FragmentTransaction transaction = fm<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.beginTransaction</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        LogCat<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.i</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"newFragment isAdded="</span> + newFragment<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.isAdded</span>())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        if (newFragment<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.isAdded</span>()) {
            transaction<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.hide</span>(mCurrentFragment)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.show</span>(newFragment)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.commitAllowingStateLoss</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        } else {
            transaction<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.hide</span>(mCurrentFragment)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.id</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.main</span>_content, newFragment)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.commitAllowingStateLoss</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        }
        mCurrentFragment = newFragment<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

然后,再switchFragment之后调用FragmentB的刷新功能,但是问题出现了,发现FragmentB里面的一些空间没有初始化,打了log之后发现,初始化在我的初始化在我的刷新功能后面执行,查了资料发现,FragmentTransaction的commit方法是异步的,难怪~

解决方法:executePendingTransactions

这里写图片描述

在用FragmentTransaction.commit()方法提交FragmentTransaction对象后,会在进程的主线程中,用异步的方式来执行。如果想要立即执行这个等待中的操作,就要调用这个方法(只能在主线程中调用)。要注意的是,所有的回调和相关的行为都会在这个调用中被执行完成,因此要仔细确认这个方法的调用位置。

于是我重写switchFragment方法

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">FragmentManager fm = getSupportFragmentManager()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        FragmentTransaction transaction = fm<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.beginTransaction</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        if (fragment<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.isAdded</span>()) {
            transaction<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.hide</span>(mCurrentFragment)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.show</span>(fragment)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.commitAllowingStateLoss</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        } else {
            transaction<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.hide</span>(mCurrentFragment)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.id</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.main</span>_content, fragment)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.commitAllowingStateLoss</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        }
        mCurrentFragment = fragment<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>


        fm<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.executePendingTransactions</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        ((DiscoverFragment) fragment)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.refresh</span>(searchWord)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul><div class="save_code tracking-ad" data-mod="popu_249" style="box-sizing: border-box; position: absolute; height: 60px; right: 30px; top: 5px; color: rgb(255, 255, 255); cursor: pointer; z-index: 2;"><a target=_blank target="_blank" style="box-sizing: border-box; color: rgb(12, 137, 207);"><img src="http://static.blog.csdn.net/images/save_snippets.png" style="border: none; box-sizing: border-box;" alt="" /></a></div><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

多加了一句fm.executePendingTransactions()

猜你喜欢

转载自blog.csdn.net/jbb0403/article/details/52814149