Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 編寫原生看書頁面 輪播圖模塊時遇到的fragment問題

編寫原生看書頁面 輪播圖模塊時遇到的fragment問題

編輯:關於Android編程

書籍頁面需要顯示輪播圖組件

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.(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生命周期,如果之前創建過,就刪除,老一套:

 

	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顯示

private void switchFragment(Fragment newFragment) {

        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction transaction = fm.beginTransaction();

        LogCat.i("newFragment isAdded=" + newFragment.isAdded());
        if (newFragment.isAdded()) {
            transaction.hide(mCurrentFragment).show(newFragment).commitAllowingStateLoss();
        } else {
            transaction.hide(mCurrentFragment).add(R.id.main_content, newFragment).commitAllowingStateLoss();
        }
        mCurrentFragment = newFragment;
    }

然後,再switchFragment之後調用FragmentB的刷新功能,但是問題出現了,發現FragmentB裡面的一些空間沒有初始化,打了log之後發現,初始化在我的初始化在我的刷新功能後面執行,查了資料發現,FragmentTransaction的commit方法是異步的,難怪~

解決方法:executePendingTransactions

這裡寫圖片描述

在用FragmentTransaction.commit()方法提交FragmentTransaction對象後,會在進程的主線程中,用異步的方式來執行。如果想要立即執行這個等待中的操作,就要調用這個方法(只能在主線程中調用)。要注意的是,所有的回調和相關的行為都會在這個調用中被執行完成,因此要仔細確認這個方法的調用位置。

於是我重寫switchFragment方法<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> FragmentManager fm = getSupportFragmentManager(); FragmentTransaction transaction = fm.beginTransaction(); if (fragment.isAdded()) { transaction.hide(mCurrentFragment).show(fragment).commitAllowingStateLoss(); } else { transaction.hide(mCurrentFragment).add(R.id.main_content, fragment).commitAllowingStateLoss(); } mCurrentFragment = fragment; fm.executePendingTransactions(); ((DiscoverFragment) fragment).refresh(searchWord);

多加了一句fm.executePendingTransactions()

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved