1、對(duì)比v4包與app包下的Fragment,有哪些不同點(diǎn),使用時(shí)該注意哪些?
①android.support.v4.app.Fragment:V4的兼容性更強(qiáng),其可以兼容到android:minSdkVersion="4",就是android的版本號(hào)是1.6.
android.app.Fragment的兼容性的最低版本是android:minSdkVersion="11",就是android的3.0版本
②在運(yùn)用的時(shí)候倒入的包不同
③繼承的父類不同,v4的Fragment的FragmentManager fm = getSupportFragmentManager(),并且當(dāng)前的Activity需要繼承自FragmentActivity.
android.app.Fragment是通過(guò)FragmentManager fm = getFragment(),并且當(dāng)前的Activity繼承自Activity即可。
④使用的時(shí)候:V4的Fragment可以通過(guò)靜態(tài)加載的方法在布局文件中<fragment>來(lái)使用。
但是android.app.Fragment需要也能通過(guò)<fragment>標(biāo)簽來(lái)加載,需要在程序中動(dòng)態(tài)的通過(guò)add,replace的方法來(lái)使用。但是其繼承的是Activity.
⑤注意,不管用哪一個(gè)包下面的,都必須完全運(yùn)用那個(gè)包下面的。
⑥對(duì)于v4,需要在project structure中的dependencies中添加v4的包。
2、為什么創(chuàng)建Fragment時(shí)傳遞參數(shù)要用setArguments()
在導(dǎo)入V4的Fragment的時(shí)候是沒(méi)有有參數(shù)的構(gòu)造函數(shù)的,所以不能通過(guò)構(gòu)造函數(shù)的方式去傳遞值。
在Activity在異常情況下退出的時(shí)候,比如切換橫屏幕,豎屏幕的時(shí)候,會(huì)將臨時(shí)數(shù)據(jù)存放在Bundle中,如果不用setArguments的時(shí)候,則會(huì)出現(xiàn)數(shù)據(jù)丟失,切換屏幕之后就無(wú)法顯示了。
3、 將Fragment添加到Activity中的方式有哪些,有何區(qū)別。
靜態(tài)添加:將Fragment作為一種組件,在布局文件中進(jìn)行添加,不過(guò)要指明android:name,即將Fragment放到這個(gè)布局中,這樣的話,在靜態(tài)添加的fragment中就不能實(shí)現(xiàn)fragment的切換,替代等。
動(dòng)態(tài)添加:需要在布局文件中有一個(gè)Fragment的容器。在動(dòng)態(tài)添加的時(shí)候,首先需要一個(gè)Fragment管理器,即FragmentManager,在android.app.Fragment中直接通過(guò):FragmentManager fm = getFragmentManager(),而在v4的包中需要通過(guò)FragmentManager fm = getSupportManager()的形式獲取。再在拿到FragmentManager的基礎(chǔ)之上,得到FragmentTransication,來(lái)對(duì)Fragment來(lái)做一系列的操作。
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
4、FragmentTransaction里面一些基本方法說(shuō)明,比如add()/show()
這些方法是在動(dòng)態(tài)加載Fragment中,對(duì)Fragment做的一系列的事務(wù)性操作
add():向Activity中添加一個(gè)Fragment,有三個(gè)重載的方法。
remove():從Activity中移除一個(gè)Fragment
replace():使用一個(gè)Fragment替換當(dāng)前的一個(gè)Fragment
hide():隱藏當(dāng)前的Fragment,不會(huì)調(diào)用生命周期的方法
show():顯示之前隱藏的Fragment,不會(huì)調(diào)用生命周期的方法
detach():會(huì)將View從UI中移除,detach()之后可以調(diào)用attach()來(lái)進(jìn)行恢復(fù)
attach():重建View視圖,附加到UI上并顯示
5、動(dòng)態(tài)添加add()方法,各參數(shù)的意義,tag作用?(findFragmentByTag)
有三個(gè)重載的add()方法:
add(Fragment,Tag):Tag的作用就是可以通過(guò)getFragmentManager.findFragmentByTag的方式來(lái)獲取一個(gè)fragment,然后把它當(dāng)成一個(gè)view來(lái)操作。(無(wú)UI布局,onCreateView是無(wú)效的)
add(id,Fragment):注意前面的id是一個(gè)ViewGroup的id,后面是一個(gè)fragment的對(duì)象。
add(id,Fragment,Tag):
當(dāng)Fragment沒(méi)有UI的時(shí)候,可以通過(guò)findFragmentByTag來(lái)找到這個(gè)Fragment,這里不需要在Fragment中寫onCreateView的方法,通過(guò)add(fragment,Tag)的方式去添加Fragment.
6、FragmentTransaction,一次事務(wù)中可以進(jìn)行多個(gè)操作,比較commit()、commitNow()、commitAllowingStateLoss(),區(qū)別?
事物的提交方式有4種,commit(),commitAllowingStateLoss(),commitNow(),commitNowAllowingStateLoss()
commit():在主線程中異步執(zhí)行,需要等待主線程的調(diào)度,其在使用的時(shí)候FragmentManager會(huì)檢查是否已經(jīng)保存了其狀態(tài),如果狀態(tài)已經(jīng)保存了,則就拋出IllegalStateException異常。就是說(shuō)commit()需要在宿主Activity保存狀態(tài)之前調(diào)用,否則就會(huì)報(bào)錯(cuò)。(因?yàn)槿绻鸄ctivity出現(xiàn)異常需要恢復(fù)狀態(tài),在保存狀態(tài)之后的commit()將會(huì)丟失,這和調(diào)用的初衷不相符合。
commitAllowingStateLoss():也是一個(gè)異步操作,但是其允許Activity保存狀態(tài)之后調(diào)用,也就是說(shuō)遇到狀態(tài)丟失不會(huì)報(bào)錯(cuò)。(在狀態(tài)出錯(cuò)是可以接受的情況下使用)
commitNow():是同步執(zhí)行的操作,需要在Activity執(zhí)行保存狀態(tài)之前來(lái)進(jìn)行操作。否則會(huì)拋出異常。(FragmentManager.excutePendingTranscantions()也表示一下執(zhí)行提交操作,但是其會(huì)把所有的任務(wù)一次性提交,這樣有可能會(huì)有副作用)遇到狀態(tài)丟失不會(huì)報(bào)錯(cuò)。
commitNowAllowingStateLoss():是一個(gè)同步操作,但是允許在Activity保存狀態(tài)之后調(diào)用。
7、 AllowingState原因,解決AllowingState異常有哪些方法
當(dāng)Activity異常銷毀的時(shí)候會(huì)調(diào)用onSaveInstanceState(),來(lái)保存狀態(tài)信息,但是如果commit在保存狀態(tài)信息之后操作,那么久相當(dāng)于給Activity重新添加了一個(gè)fragment,這個(gè)時(shí)候的fragment的狀態(tài)和上一個(gè)的fragment的狀態(tài)不一樣,所以就會(huì)報(bào)狀態(tài)不正確的異常。可以通過(guò)commitAllowingState的方式。
8、onSaveInstanceState()、onPause()、onStop()三者的生命周期順序?
onSaveInstanceState()并不是每一次Activity的生命周期都會(huì)調(diào)用的,其只是用于在異常情況下銷毀Activity的時(shí)候調(diào)用,保存的是和當(dāng)前Activity狀態(tài)相關(guān)的臨時(shí)數(shù)據(jù)。
onPause(),onStop()也可以用于保存一些數(shù)據(jù),但是保存的都是持久化的數(shù)據(jù)。
若啟動(dòng)ActivityB之后,選擇點(diǎn)擊Home按鈕,程序退到后臺(tái),那么執(zhí)行順序是:B:onPause -> B:onSaveInstanceState -> B:onStop。
程序在后臺(tái)的時(shí)候,選擇主動(dòng)殺死程序進(jìn)程,然后再?gòu)淖烂纥c(diǎn)擊應(yīng)用啟動(dòng),會(huì)顯示之前的ActivityB,執(zhí)行順序是:B:onCreate -> B:onStart –> B:onRestoreInstanceState - > B:onResume。
onSaveInstanceState()在Activity的onPause()的情況后再調(diào)用。
onRestoreSaveInstanceState()在Activity的onResume之前調(diào)用。
9、Fragment事務(wù)中加不加addToBackStack()的區(qū)別,popBackStack()?
addToBackStack()的用途是是否將一次的事務(wù)操作加入到回退棧,官方的說(shuō)法是是否要在回退的時(shí)候顯示上一個(gè)Fragment.
addToBackStack()保存的是一系列針對(duì)一個(gè)fragmentTransaction的操作記錄,表示是否將上一次的Fragment加入到回退棧中,如果加入,則按back鍵的時(shí)候,前面的Fragment就會(huì)顯示出來(lái)。如果不加入,前面的fragment就不會(huì)顯示出來(lái)。
popBackStack(); 彈出堆棧中的一個(gè)并且顯示,也就是代碼模擬按下返回鍵的操作。
10、 Fragment向Activity傳遞數(shù)據(jù)、Activity向Fragment傳遞數(shù)據(jù)、Fragment之間通信
Fragment之間的通信:
可以通過(guò)Activity這個(gè)中間媒介來(lái)實(shí)現(xiàn)。在一個(gè)Fragment中通過(guò)Activity(getActivity()方法來(lái)獲得Activity的實(shí)例)獲取到另外一個(gè)Fragment,再調(diào)用另外一個(gè)Fragment的相關(guān)方法來(lái)實(shí)現(xiàn)通信。
Fragment向Activity傳遞數(shù)據(jù):
通過(guò)接口的方式,在外部聲明一個(gè)接口,在Fragment的Attach()的方法中去實(shí)例化Listener(該接口強(qiáng)轉(zhuǎn)為activity類型便可和Activity有交際),在Fragment的onCreateView的方法中調(diào)用接口中的返回發(fā),并放置相應(yīng)的參數(shù)。接口的實(shí)現(xiàn)方法在Activity中來(lái)實(shí)現(xiàn),拿到參數(shù)做一些與Activity更新界面相關(guān)的事情。
Activity項(xiàng)Fragment中傳遞數(shù)據(jù):
1、setArguments(Bundle)的方式去傳遞數(shù)據(jù),然后在Fragment的onCreateView的方法中去getArgments()獲取Bundle.
2、在Activity中定義返回某個(gè)需要傳遞參數(shù)的值,然后在Fragment的onAttach()方法中去調(diào)用這個(gè)方法,取到這個(gè)值。
11、DialogFragment
①可以有類似于Fragment一樣的生命周期,便于管理
②DialogFragment可以自定義顯示的布局,與普通的Dialog不一樣,(普通的Dialog只是通過(guò)builder的方式去構(gòu)建對(duì)話框)
③一般的Dialog在切換屏幕(Activity異常銷毀再重建)的時(shí)候不會(huì)保存狀態(tài)。
④在DialogFragment在切換屏幕的時(shí)候會(huì)保存狀態(tài)。
12、ViewPager+Fragment相關(guān)
一般用到上述的時(shí)候需要在Fragment左右滑動(dòng)的時(shí)候去切換Fragment.
首先要在布局文件中加一個(gè)組件ViewPager的組件,這里需要導(dǎo)入的是v4下的包,主要是在使用Adapter的時(shí)候用的是FragmentPagerAdapter來(lái)關(guān)聯(lián)ViewPager和Fragment,這個(gè)Adapter繼承自ViewPager,在V4的包下。
在Activity中獲取到ViewPager組件,再把Fragment添加進(jìn)去。
可以對(duì)ViewPager設(shè)置監(jiān)聽(tīng)滑動(dòng),setOnPageChanged(..)
13、 FragmentPagerAdapter和FragmentStatePagerAdapter的區(qū)別“
FragmentPagerAdapter:在Fragment較少的情況下使用,主要是會(huì)把Fragment加入到內(nèi)存,占用內(nèi)存,F(xiàn)ragment不在viewPager.setOffscreenPageLimit()的保護(hù)的范圍內(nèi)會(huì)調(diào)用FragmentManager的detach()方法,相應(yīng)的Fragment的onDestroyView會(huì)執(zhí)行,但Fragment實(shí)例仍在
FragmentStatePagerAdapter:在Fragment較多的情況下使用,不會(huì)把Fragment加載到內(nèi)存,當(dāng)其中一個(gè)Fragment劃過(guò)去的時(shí)候,這個(gè)Fragment就會(huì)被銷毀,當(dāng)需要可見(jiàn)的時(shí)候再重新創(chuàng)建這個(gè)fragment的實(shí)例。
14、懶加載
懶加載的意思就是需要的時(shí)候才去加載
在ViewPager需要包含多個(gè)Fragment的時(shí)候,其在第一個(gè)Fragment創(chuàng)建的時(shí)候,其他的Fragment也相應(yīng)的創(chuàng)建好了,及走了onAttach,onCreate,onCreateView,onActivityCreate,onStart,,onResume.Fragment的 onResume()表示的是當(dāng)前Fragment處于可見(jiàn)且可交互狀態(tài),但由于ViewPager的緩存機(jī)制,它已經(jīng)失去了意義,也就是打開(kāi)第一個(gè)Fragment,但其實(shí)其他的Fragment的數(shù)據(jù)也都已經(jīng)加載好了。如果加載數(shù)據(jù)的操作都比較耗時(shí)或者都是類似圖片的占用大量?jī)?nèi)存,這時(shí)就應(yīng)該考慮想想是否該實(shí)現(xiàn)懶加載。
懶加載的實(shí)現(xiàn)方式:通過(guò)setVisible的方式,當(dāng)用戶對(duì)于當(dāng)前的Fragment可見(jiàn)的時(shí)候去加載。如果可見(jiàn),則再在onCreateView中去請(qǐng)求數(shù)據(jù),初始化界面等操作。
15、 setUserVisibleHint調(diào)用時(shí)機(jī)
在切換Fragment的時(shí)候會(huì)調(diào)用,當(dāng)fragment即將可見(jiàn)(在onAttach()之前),和即將不可見(jiàn)的時(shí)候就會(huì)調(diào)用。主要是設(shè)置一個(gè)標(biāo)志位,用于懶加載。