android學習之Fragment與Activity的綁定
最近項目忙完了,老大又不讓我做android了,總之快速開發接觸的東西會很多,只要能解決問題的都是好方法,但從個人的角度而言,快速的開發讓人無法深入瞭解一些技術,雖然現在在項目中可能不會做android了,但是既然開始學習了就不要放棄,繼續自己的學習。
Fragment在android中被稱為片段,該技術的引入主要是解決android開源的多種螢幕適配問題,在平板、手機、電視都在使用android的情況下,單純的採用activity會導致UI的單一,Fragment為瞭解決這種問題在android sdk11中引入。fragment需要綁定到activity中才能運行。
Fragment和Activity在某種程度有一定的相似性,也有類似的生命週期。但是Fragment必須依附於Activity,同時Activity不能被替換、刪除等操作,而Fragment允許被替換和刪除。
Fragment可以通過UI控制項fragment綁定對應的Fragment也可以採用動態添加方式。兩種方式,第一種相對比較簡單,而第二種則更加的靈活,通常是實際使用中合理的選擇其中的一種方式。Fragment的靈活性大於Activity,因此目前android的設計中推崇AUF,就是所有的都使用Fragment。
第一種方式的實現通常在XML的布局檔案中顯示的定義對應的Fragmet的資訊。
- <fragment xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/helloFragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:name="com.example.hell.HelloFragment">
- </fragment>
其中的android就是對應的Fragment的類名,這種方式不能方便的進行擴充和取消。
在最近的學習中,較好的體驗了android設計的MCV思想,M通常是指資料相關的模型,也就是設計相關的資料模組,這種將設計的會使得資料是獨立於其他組件的,C是指控制模組,這個模組會實現UI顯示與資料的關聯,實現具體的控制關聯,V是指顯示功能,將相關的資料資訊通過控制顯示出來。因此在android的功能設計的過程中最好將相關的資料資訊作為單獨的類,並提供管理這些資料的單一執行個體工具類,通過這個工具類,控制相關的組件能夠訪問到這些資料資訊。
這些也是在看了一些代碼之後的感想而已。AUF的思想通常使得在建立一個activity的過程中都需建立一個對應的Fragment的對象,對應的activity的layout只是提供簡單的Fragment容器。
- <?xml version="1.0" encoding='utf-8'?>
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/fragmentContainer"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
而關於fragment的布局則是實際需要顯示的相關ui布局。
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/crime_title_label"
- style="?android:listSeparatorTextViewStyle"
- />
- <EditText
- android:id="@+id/crime_title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="@string/crime_title_hint"
- />
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/crime_details_label"
- style="?android:listSeparatorTextViewStyle"
- />
- <Button
- android:id="@+id/crime_date"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- />
- <CheckBox
- android:id="@+id/crime_solved"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:text="@string/crime_solved_label"
- />
- </LinearLayout>
這樣設計的好處是activity不需要針對特定的ui布局,更像是一個通用的布局,所有的fragment都可以再其中添加。而Fragment則需要實現具體的UI布局,這樣也從實現上將activity和具體的UI顯示獨立開來,實現了Fragment的動態添加和UI切換。因此activity更多的是管理Fragment。
Fragment的綁定實現
在AUF的實現中有一種比較常用的方式就是單Fragment的Activity。也就是只有一個Fragment和Activity進行綁定,因此可以提供一個通用的方法用於實現fragment與activity的綁定關係,也就是實現一個單Fragment綁定的Activity類。這樣所有的Fragment需要綁定到一個具體的Activity的過程中只需要建立對應的Fragment對象,關於綁定的操作就有該抽象類別完成。在代碼中添加Fragment的實現會使用到一個Fragment的管理器FragmentManager,這個管理器的操作有點兒類似資料庫的事物處理操作過程。具體的實現過程如下所示:
- public abstract class SingleFragmentActivity extends FragmentActivity {
- protected abstract Fragment createFragment(); <<----該方法用於建立不同的Fragment對象
- @Override
- protected void onCreate(Bundle arg0) {
- super.onCreate(arg0);
- setContentView(R.layout.activity_fragment);
- /* 擷取管理器*/
- FragmentManager fm = getSupportFragmentManager();
- Fragment fragment = fm.findFragmentById(R.id.fragmentContainer); //R.id.fragmentContainer就是容器
- if (fragment == null) {
- /* 在activity中添加對應的Fragment的過程*/
- fragment = createFragment();
- fm.beginTransaction() //具體的操作類似資料庫的交易處理過程
- .add(R.id.fragmentContainer, fragment)
- .commit();
- }
- }
- }
在具體的實現某一個activity的過程中只需要實現對應的抽象函數Fragment createFragment(),同時所有的activity可以通用同一個布局檔案。以上的代碼實現了一個Fragment和activity的綁定過程,也就是需要使用FragmentManager進行控制。
- public class CrimeActivity extends SingleFragmentActivity {
- @Override
- protected Fragment createFragment() {
- //實現具體的建立過程
- }
- }
這樣的對於activity就非常的通用,因此在這種單一fragment的情況下可以採用通用的activity。
關於createFragment的實現方式,其實可以針對不同的activity分別實現代碼,但是在實際使用過程中都是採用其中一個activity中的Fragment啟動另一個activity的方式,因此可能會傳遞一些參數,而這些參數時針對activity的,而為了實現AUF的思想,在其實activity的過程中就應該啟動對應的Fragment。
有時候Fragment有一些歸屬於當前對象的參數資訊需要儲存,當然可以儲存到歸屬的activity中,但是考慮到統一性,通常會考慮添加Fragment的Bundle參數,關於Fragment的Bundle參數有點兒類似Activity的Bundle參數,用於儲存一些重要的資訊,但是Fragment的Bundle參數需要在添加到Acitvity之前綁定,考慮到Fragment的通用性,可以為每一個建立的Fragment都添加一個對應的Bundle argement。具體如下所示:
- publicclassCrimeFragment extends Fragment{
- ...
- /* 這是fragment實現bundle的基本規則,在建立fragment的過程中不要調用建構函式 */
- /* 該函數必須為static方法,不然必須先建立對應的對象才能建立fragmet*/
- public static CrimeFragment newInstance(UUID crimeId) {
- Bundle args = new Bundle(); //建立bundle參數對象
- args.putSerializable(EXTRA_CRIME_ID, crimeId); //填充對應的key-word對
- CrimeFragment fragment = new CrimeFragment(); //建立對應的Fragment類
- fragment.setArguments(args); //邦對對應的bundle參數
- return fragment;
- }
- ...
- }
這樣就可以在對應的activity中去實現對應的createfragment方法了,具體實現如下所示:
- public class CrimeActivity extends SingleFragmentActivity {
- @Override
- protected Fragment createFragment() {
- UUID crimeId = (UUID) getIntent()
- .getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);
- //該參數來自activity,通過newInstance將參數傳遞給了Fragment
- return CrimeFragment.newInstance(crimeId);
- }
- }
雖然newInstance()的實現方法也可以在Activity的createFragment函數實現中完成,但是考慮到可重用性,將Fragment的綁定關係由Fragment實現更加的通用。
通過這種方式,就可以在其中的一個Activity的Fragment中啟動另一個Activity中的Fragment。因此基本的實現過程如下所示.
SinalFragmentActivity(完成Fragment與Activity的綁定操作)
|
V
XXXActivity (實現具體Fragment的建立操作)
|
V
擷取activity的參數,然後調用Fragment的綁定Bundle的建立函數
XXXFragment
|
V
定義靜態建立執行個體方法,該方法中實現bundle和Fragment的綁定關係
因此Activity的類的實現方法如下所示:
- public class CrimeActivity extends SingleFragmentActivity {
- @Override
- protected Fragment createFragment() {
- UUID crimeId = (UUID) getIntent()
- .getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);
- //擷取activity的參數,並通過newInstance函數將對應的參數與、Fragment進行綁定
- return CrimeFragment.newInstance(crimeId);
- }
- }
這種實現方法較好的實現了AUF中單Activity和Fragment的綁定實現,這種綁定實現對於Activity的布局非常通用,定義的抽象類別也實現了Fragment和Activity的綁定關係。只需要實現對應Fragment的建立操作,為了進一步的實現,要求Fragment提供一種綁定Bundle的靜態方法實現一個對象的建立,並綁定了一個bundle的對象。
這種實現方法主要是為了遵循AUF的實現,其實並不需要實現的這麼複雜,但是從可重用性的角度分析,這樣的實現方法是非常不錯的。
有一些優秀的分析可以去拜讀一下。
http://www.cnblogs.com/xinye/archive/2012/08/28/2659712.html
http://blog.csdn.net/guolin_blog/article/details/8881711
參考文獻:
Android Programming: The Big Nerd Ranch Guide 第10章