# **Fragment**
* * * * *
1. Fragment是什么
2. Fragment能實現哪些效果?為什么我要使用Fragment
3. Fragment的具體使用細節?
4. 如何向別人講解,熟練使用Fragment?
## **一.Fragment是什么?**
Fragment是Android系統提供的“組件”[1],以提供“靈活構建UI布局”能力。
> 注:什么是組件?組件,是由系統/依賴庫等其他外部因素創建的“Java類”,它們存在的形式,通常是Java類;不同組件唯一的不同之處是——不同的組件,提供各不相同的“能力”。
>
## **二.Fragment經常出現在哪些經典的UI布局當中?**
* 左右布局,如新聞模塊、側邊欄導航模塊、外賣點餐系統
* 點擊列表查看詳情布局,如新聞列表-查看新聞詳情
* 常見tab切換頁
* 此次研究對象,漫畫APP中,使用到Fragment的模塊和頁面:
1. 主頁
2. 點擊側邊欄顯示詳情內容
## **三.如何開始使用Fragment?**
為了保證資料來源的權威性,本人將直接引用Google官方提供的Android開發資料
在使用Fragment之前,再次明確我作此小節的目的:
學會創建、實現、定義、引用Fragment。——是本小節的核心、也是我作此文的目的
注意,在確保諸位能學會Fragment之前,一定要牢記這里包含了四步曲:
前兩步定義、創建、實現只是作好了”食材“;
第三、四步正確定義、引用Fragment,才能真正的發揮Fragment功力,進而用Fragment作出”美味可口的大餐“。
我都有點迫不及待了,快來和我一起了解Fragment使用方法吧!
### **創建和實現Fragment**
創建Fragment的方式一共有兩步:代碼創建Java類和XML創建視圖布局。
創建Java文件的步驟如下:
在你的src/main/java 目錄下,創建一個名為ArticleFragment的文件,粘貼復制下面的代碼
~~~
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.ViewGroup;
public class ArticleFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.article_view, container, false);
}
}
~~~
瞧,動態創建的方式如此簡單,就跟我們初學Java時,創建一個Person類那樣簡單,不同的是,我們需要通過import導入Android的開發包;當然,按住ctrl+shift+o,即可快速導入Fragment關聯的包;還有關鍵的一點,在實際開發中,上述代碼將會被重復寫無數多次,你有的是機會去記住這段代碼。而此刻,我們學習的重點是——哪一段代碼,可以創建Fragment,因此,作為新手,我建議直接粘貼復制此段代碼。以便于進行下一步練習。
我們再來看看創建Fragment視圖布局的方式,也就是說,我們即將實現Fragment的能力——UI布局:
在你的res/layout/目錄下創建news_articles.xml文件,直接粘貼復制下面的布局語法
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
瞧,依然是如此的簡單!我們在xml文件中,加入了TextView文本組件,這即將是Fragment要顯示的內容
我們通過在Java目錄下創建Java文件,在laout目錄下創建xml文件的形式,完成了第一步:Fragment的創建。可是,完成創建和實現,并不意味著就萬事大吉了,我們還需要實現它、正確定義、引用它,才能在手機屏幕上看到Fragment這個可愛的家伙!
### **定義Fragment**
老實說,定義Fragment并不簡單,動態定義和靜態定義
動態定義,在Java文件中通過new ArticleFragment()的方式,直接完成對Fragment的定義,這樣引用,也是動態引用的
靜態定義,是在諸如res/laout/activity_home.xml中(知識舉例),創建Fragment,通過引用activity.xml中的fragment,完成靜態定義、這樣定義,引用方式也稱之為靜態引用
先說靜態引用,這是我們上一步創建的
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment android:name="com.example.android.fragments.ArticleFragment"
android:id="@+id/article_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
引用Fragment
下列這段代碼,講解了在activity中靜態引用fragment,這樣activity講直接顯示news_articles.xml里的布局,連fragment得實例化對象都還沒看到!
~~~
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
}
}
~~~
這種靜態引用的核心,就是通過系統已經定義好的函數——setContentView()直接加載指定的xml布局文件
記住,setCOntentView()函數,這個函數相當關鍵。
接著講動態引用,動態引用Fragment,正是本文核心中的核心。實際開發,也是用的最多的!
先在res/layout/目錄下創建news_article.xml文件,語法如下
~~~
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
~~~
上述語法只是創建了一個framelayout布局(不是fragment布局),沒有任何內容
(在看下面這段代碼之前,先使用第一步創建ArticleFragment的方式,再創建一個類似的名為HeadlineFragment的Fragment)
~~~
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create a new Fragment to be placed in the activity layout
HeadlinesFragment firstFragment = new HeadlinesFragment();
// In case this activity was started with special instructions from an
// Intent, pass the Intent's extras to the fragment as arguments
firstFragment.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
}
~~~
上述代碼有三處關鍵的地方
1. setContentView(R.layout.news_articles);
2. HeadlinesFragment firstFragment = new HeadlinesFragment();
3. getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, firstFragment).commit();
解釋和說明:
1. 先為Activity加載布局,Activity此刻只有一個framelayout空布局
2. 再動態創建一個Fragment子類對象——HeadlinesFragment
3. 最最關鍵的,第三段超長的代碼鏈,一句話、一個標點符號都不能錯。
**最為關鍵**的是.add(R.id.fragment_container, firstFragment)
R.id.fragment_container指的是activity首先加載的framelayout空布局id,
而firstFragment指的是fragment對象,通過add()函數,firstFragment講被添加到activity中,從而顯示到屏幕上!
當然,千萬別忘了commit()!只有確保commit,才能保證系統正確的執行你前面寫的一大段代碼!
## **四.Fragment的使用細節**
老實說,Fragment的使用細節,沒什么值得講的地方,新手如果確保前三小節看懂、會用,避免語法錯誤、步驟錯誤,使用Fragment就不可能出現BUG。
但有幾點,值得我分享給諸位,坐下來好好談談的技術點:
1. 先再次復述一遍Fragment的創建、實現、定義、引用的步驟,尤其是動態引用小節中的第三步,那段超長的代碼鏈,是否倒背如流?
2. Acitivity、Fragment、FragmentManager、FragmentTransaction,
2.1Activity與Fragment的關系——生命周期是如何影響Activity和Fragment的
2.1FragmentTransaction的API,除了add(),試試其他方法replace()、hide()、remove()等
細節部分,互聯網上有太多的Android同仁介紹過了,寫多了,對于本人,不能給予Android領域更多貢獻,在這里便不多費口舌,獻出我認為較好的關于“Fragment使用細節”的鏈接,有興趣的可以深究。
1.Android API網站——FragmentTransaction索引
https://developer.android.google.cn/reference/android/app/FragmentTransaction.html
2.Android Fragment培訓課程
https://developer.android.google.cn/training/basics/fragments/index.html
2.Android Fragment 真正的完全解析(下)
http://blog.csdn.net/lmj623565791/article/details/37970961/
## **五.學會向別人講解Fragment**
當你有向別人講解Fragment的需要時,你一定身處下面兩種角色之一:畢業答辯、求職招聘。
* 參與畢業答辯的同學,擔心被老師問到Fragment,手慌腳亂,不知從何說起
* 即將參加求職招聘的同仁,不善言辭的程序員,緊張起來,也容易亂說一通。
此節的目的,正在于此。
#### 1.Fragment是什么
答:谷歌提供的碎片化組件,可以附著在Activity上,組成多個碎片布局。
#### 2.Fragment如何用,
3.FragmentManager 、FragmentTransition是Fragment的管理器和發布器,管理器既可以將Fragment綁定至Activity上,也可以創建發布器對象。一旦創建好了發布器對象,發布器FragmentTransition便可通過commit()函數,通知Actiivty,將Fragment添加到屏幕之上。
#### 3.Fragment如何管理?
這里的管理,往小了說,是通過管理器FragmentManager管理的,FragmentManager有強大、全面的管理Fragment的函數,對Fragment的操作,包括索引、查找、增加、刪除、壓棧、出棧、回退等功能。時間以及瞬時記憶力等原因,不在這里一一說明了。
但有一點,是面試、答辯值得一說的,就是Fragment管理器,能實現哪些常見的需求?
比如查找,可以找到已經創建且并未銷毀的Fragment,這樣可以復用對象,減少內存消耗;
比如增加,可以繼續創建一個Fragment,附著在Activity上,舊的Fragment,只是看不見、或者暫時存放至后臺了
比回退,可以實現瀏覽器打開一系列頁面,按住Back鍵位,還能從當前頁面,返回到上一歷史頁面去,這在實際開發,是相當有用的。
但具體的API,面試、答辯,并不一定需要說出來,最重要的是,講出來,Fragment以及Fragment的管理器、發布器,可以實現哪些功能和需求,實際開發,是允許我們去查詢資料和文檔的!