1.Fragment概要python
學習Fragment的時候能夠聯繫以前學習過的Activity,由於它們有不少類似點:均可包含佈局,有本身的生命週期,Fragment可看似迷你活動。正如Fragment的名字--碎片,它的出現是爲了解決Android碎片化 ,它可做爲Activity界面的組成部分,可在Activity運行中實現動態地加入、移除和交換。一個Activity中可同時出現多個Fragment,一個Fragment也可在多個Activity中使用。活動和碎片像極了夫妻, 雖然緊密聯繫可是又有獨立空間,在一塊兒讓彼此變得更好。android
下面這個很是經典的例子更直觀地說明了Fragment做用:app
2.Fragment生命週期佈局
先來看官方文檔提供的有關Fragment生命週期的圖片。post
是否是能發現Fragment和Activity的生命週期太類似了,如今只須要再介紹幾個Activity中沒講過的新方法:學習
onAttach():當Fragment和Activity創建關聯時調用spa
onCreateView():當Fragment建立視圖時調用操作系統
onActivityCreated():當與Fragment相關聯的Activity完成onCreate()以後調用設計
onDestroyView():在Fragment中的佈局被移除時調用3d
onDetach():當Fragment和Activity解除關聯時調用
在上圖中畫了幾條線,能夠看到Fragment週期中的狀態幾乎都是成對出現的,因此不難理解下圖幾種變化下Fragment生命週期方法的調用順序了。
加載到Activity中的Fragment在各類變化下方法的調用順序更值得注意。須要提一句的是,Activity的FragmentManager負責調用隊列中Fragment的生命週期方法,只要Fragment的狀態與Activity的狀態保持了同步,託管Activity的FragmentManager便會繼續調用其餘生命週期方法以繼續保持Fragment與Activity的狀態一致。
Fragment生命週期與Activity生命週期的一個關鍵區別就在於,Fragment的生命週期方法是由託管Activity而不是操做系統調用的。Activity中生命週期方法都是protected,而Fragment都是public,也能印證了這一點,由於Activity須要調用Fragment那些方法並管理它。
3.加載Fragment方法
如今就來學習如何在Activity中加載Fragment。
(1)靜態加載:在託管Activity的layout文件中聲明Fragment
靜態加載Fragment大體過程如圖,分紅四步:
下面經過一個簡單的例子感覺Fragment靜態加載到Activity的過程。
第一步:新建frag_layout.xml,爲Fragment指定一個佈局,這裏簡單的放一個TextView和一個Button。
第二步:新建一個MyFragment類並繼承Fragment,這裏引用android.app包下的就能夠,另外一個包下主要用於兼容低版本的安卓系統。而後重寫 onCreateView() 方法,這個方法裏經過LayoutInflater的inflate()方法將剛剛定義的frag_layout佈局加載進來並獲得一個View,再return這個View。
第三步:新建mian.xml,做爲Activity的佈局,使用< fragment>標籤添加碎片,而且必定要有android:name屬性且值爲被加載的Fragment類的包名.類名完整形式。
第四步:在MainActivity中加載main佈局。如今MyFragment就完成了靜態加載到MainActivity中,這時碎片裏的控件天然也是活動的一個部分,可直接在活動中獲取到Button的實例,來註冊點擊事件了。
運行一下看看能不能達到效果:
(2)動態加載:在託管Activity經過代碼動態添加
動態加載的代碼也很是簡單,直接看例子。修改main.xml,將整個< fragment>刪掉。但還保留一個LinerLayout的空間而且還給了Id,爲什麼這樣作?立刻揭祕。
接下來在MainActivity中添加幾行代碼:
可將整個過程大體分爲三個步驟:
第一步,先用 getFragmentManager() 方法獲取一個FragmentManager對象,再經過它的 beginTransaction() 獲取一個FragmentTransaction的實例。
第二步,用beginTransaction. add() 方法將MyFragemnt實例添加到main佈局裏LinearLayout裏,終於知道以前鋪墊的Id是怎麼回事了。必定要注意,add()方法裏的第一個參數是容器視圖資源Id,而不是layout。容器視圖資源Id有兩個做用:告知FragmentManager,碎片視圖應該出如今活動視圖的什麼地方;它也是FragmentManager隊列中碎片的惟一標識符。而靜態加載時碎片的惟一標識符正是在活動佈局裏< fragment>下的id。
第三步:調用beginTransaction. commit() 提交。另外,若是容許用戶經過按下返回按鍵返回到前一個Fragment狀態,在調用commit()以前先調用 addToBackStack(true) 方法。
這裏注意到動態加載進來的Fragment裏的控件並不能直接在活動中findViewById獲得,那麼如何實現點擊效果呢,學完下一個知識點就有辦法了。
4.Fragment與Activity之間通訊
在活動中能夠經過調用 FragmentManager 的 findFragmentById() 方法來獲得相應碎片的實例,繼而能夠調用碎片裏的方法。以上面demo舉例,若是想獲得靜態加載碎片的實例,可在MainActivity添加代碼以下:
MyFragment myFragment = (MyFragment)getFragmentManager(). findFragmentById(R.id.fragment);
複製代碼
若是想獲得動態加載碎片的實例,代碼以下:
MyFragment myFragment = (MyFragment)fragmentManager(). findFragmentById(R.id.layout);
複製代碼
在碎片中也能夠經過調用getActivity()方法來獲得和當前碎片相關聯的活動實例,這樣調用活動裏的方法就變得垂手可得了。好比想在MyFragment獲得MainActivity的實例:
MainActivity activity=(MainActivity)getActivity();
複製代碼
因而碎片和活動能夠很方便地進行通訊了。再想想碎片和碎片之間如何進行通訊?先在一個碎片中能夠獲得與它相關聯的活動,而後再經過這個活動去獲取另一個碎片的實例,這樣實現了不一樣碎片之間的通訊了。
如今你有沒有想到解決以前那個問題的辦法呢?能夠這樣作,修改MyFragment,代碼以下圖所示:
如今按鈕點擊就又有響應了!其實在實際開發中,若是某一板塊每次用到都須要相同的功能,就徹底能夠在碎片中實現需求,而沒必要在活動中重複代碼,這樣能夠提升代碼的複用性。
> 下一篇預告:數據存儲篇