關(guān)于Fragment肛鹏,你可能不知道的一切

省略Fragment的生命周期

省略Fragment的靜態(tài)加載

1.動態(tài)添加Fragment的方法
  • 添加有UI的Fragment

    ExampleFragment fragment = new ExampleFragment();
    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
    
  • 添加沒有UI的Fragment

    ExampleFragment fragment = new ExampleFragment();
    fragmentTransaction.add(fragment,"ExampleFragment");
    fragmentTransaction.commit();
    

    由于它并不與 Activity 布局中的視圖關(guān)聯(lián),因此不會收到對 onCreateView() 的調(diào)用蒸其。因此蹋订,不需要實(shí)現(xiàn)該方法。對應(yīng)的可以通過 findFragmentByTag("ExampleFragment")獲取Fragment實(shí)例清寇。

2.兩個(gè)Fragment與Activity之間的通信(官方建議)

前提:

  • 在Activity中有兩個(gè)Fragment,分別時(shí)LeftFragment和RightFragment
  • RightFragment會隨著LeftFragment的變化而改變(eg:點(diǎn)擊左側(cè)Fragment后右側(cè)Fragment加載詳情)

實(shí)現(xiàn):

  • 1.在LeftFragment中定義一個(gè)回調(diào)接口护蝶,Activity必須實(shí)現(xiàn)這個(gè)接口

    public static class LeftFragment extends ListFragment {
        ...
        // Container Activity must implement this interface
        public interface OnArticleSelectedListener {
            public void onArticleSelected(Uri articleUri);
        }
        ...
    }
    
  • 2.宿主Activity必須實(shí)現(xiàn)該接口

    public class MainActivity extends Activity implements OnArticleSelectedListener{
        //...省略若干代碼
        @Override
        public void onArticleSelected(Uri articleUri){
            
        }
      
    }
    
  • 3.在LeftFragment中獲取Activity實(shí)現(xiàn)接口的實(shí)例

    public static class FragmentA extends ListFragment {
        OnArticleSelectedListener mListener;
        ...
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            try {
                mListener = (OnArticleSelectedListener) activity;
            } catch (ClassCastException e) {
                throw new ClassCastException(activity.toString() + " must implement                   OnArticleSelectedListener");
            }
        }
        ...
    }
    
3.當(dāng)Activity重啟時(shí)华烟,使用Fragment保存數(shù)據(jù)

當(dāng)Activity的配置發(fā)生變化導(dǎo)致重啟時(shí),為了提高用戶體驗(yàn)持灰,一般需要在Activity銷毀的時(shí)候保存界面上的一些數(shù)據(jù)盔夜,再次創(chuàng)建的時(shí)候恢復(fù)數(shù)據(jù)。

通常的做法是在 onSaveInstanceState()回調(diào)時(shí)保存有關(guān)應(yīng)用狀態(tài)數(shù)據(jù)堤魁,然后喂链,可以在 onCreate()onRestoreInstanceState() 期間恢復(fù) Activity 狀態(tài)。

通過系統(tǒng)回調(diào)onSaveInstanceState()方法將數(shù)據(jù)保存在Boundle妥泉,但當(dāng)數(shù)據(jù)量較大時(shí)椭微,可能無法完全恢復(fù) Activity 狀態(tài),因?yàn)樗⒎窃O(shè)計(jì)用于攜帶大型對象(例如位圖Bitmap)盲链,而且其中的數(shù)據(jù)必須先序列化蝇率,再進(jìn)行反序列化,這可能會消耗大量內(nèi)存并使得配置變更速度緩慢刽沾。

在這種情況下本慕,如果 Activity 因配置變更而重啟,則可通過保留Fragment 來減輕重新初始化 Activity 的負(fù)擔(dān)侧漓。

步驟如下:

  • 1.擴(kuò)展 Fragment 類并聲明對有狀態(tài)對象(即我們要保存的對象)的引用锅尘。
  • 2.在創(chuàng)建片段后調(diào)用 setRetainInstance(boolean)
  • 3.將片段添加到 Activity布蔗。
  • 4.重啟 Activity 后藤违,使用 FragmentManager 檢索片段。

例如:

定義一個(gè)RetainedFragment用來保存數(shù)據(jù)

public class RetainedFragment extends Fragment {

    // data object we want to retain
    private MyDataObject data;

    // this method is only called once for this fragment
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // retain this fragment
        setRetainInstance(true);
    }

    public void setData(MyDataObject data) {
        this.data = data;
    }

    public MyDataObject getData() {
        return data;
    }
}

注意:盡管可以存儲任何對象纵揍,但是切勿傳遞與 Activity 綁定的對象纺弊,例如,Drawable骡男、Adapter淆游、View 或其他任何與 Context 關(guān)聯(lián)的對象。否則隔盛,它將泄漏原始 Activity 實(shí)例的所有視圖和資源犹菱。 (泄漏資源意味著應(yīng)用將繼續(xù)持有這些資源,但是無法對其進(jìn)行垃圾回收吮炕,因此可能會丟失大量內(nèi)存腊脱。)

然后,使用 FragmentManager 將片段添加到 Activity龙亲。在運(yùn)行時(shí)配置變更期間再次啟動 Activity 時(shí)陕凹,就可以獲得片段中的數(shù)據(jù)對象悍抑。

public class MyActivity extends Activity {

    private RetainedFragment dataFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // find the retained fragment on activity restarts
        FragmentManager fm = getFragmentManager();
        dataFragment = (DataFragment) fm.findFragmentByTag(“data”);

        // create the fragment and data the first time
        if (dataFragment == null) {
            // add the fragment
            dataFragment = new DataFragment();
            fm.beginTransaction().add(dataFragment, “data”).commit();
            // load the data from the web
            dataFragment.setData(loadMyData());
        }

        // the data is available in dataFragment.getData()
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // store the data in the fragment
        dataFragment.setData(collectMyLoadedData());
    }
}
4.向應(yīng)用欄添加項(xiàng)目

Fragment可以通過實(shí)現(xiàn) onCreateOptionsMenu() 向 Activity 的選項(xiàng)菜單(并因此向應(yīng)用欄)貢獻(xiàn)菜單項(xiàng)。不過杜耙,為了使此方法能夠收到調(diào)用搜骡,必須在 onCreate() 期間調(diào)用 setHasOptionsMenu(),以指示Fragment想要向選項(xiàng)菜單添加菜單項(xiàng)(否則佑女,片段將不會收到對 onCreateOptionsMenu() 的調(diào)用)记靡。

從Fragment添加到選項(xiàng)菜單的任何菜單項(xiàng)都將追加到現(xiàn)有菜單項(xiàng)之后。 選定菜單項(xiàng)時(shí)团驱,F(xiàn)ragment還會收到對 onOptionsItemSelected() 的回調(diào)摸吠。

Fragment向應(yīng)用欄添加項(xiàng)目應(yīng)用十分廣泛,例如下面的效果

我們自己也可以動手實(shí)現(xiàn)這樣的效果嚎花,先看效果:

當(dāng)切換Fragment的時(shí)候寸痢,應(yīng)用欄不同的狀態(tài),so easy紊选!

  • step1.在Fragment的onCreate回調(diào)時(shí)轿腺,調(diào)用Fragment的setHasOptionsMenu(true)方法;

    @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setHasOptionsMenu(true);
        }
    
  • step2.覆蓋onCreateOptionsMenu()方法根據(jù)不同位置加載不同的應(yīng)用欄菜單丛楚;

    @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            super.onCreateOptionsMenu(menu, inflater);
            switch (mFragmentType) {
                case 0:
                    break;
                case 1:
                    inflater.inflate(R.menu.action, menu);
                    break;
                case 2:
                default:
                    inflater.inflate(R.menu.action0, menu);
                    break;
            }
        }
    
  • step3.如果需要監(jiān)聽?wèi)?yīng)用欄的點(diǎn)擊族壳,只需要覆蓋onOptionsItemSelected()方法。

    @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    Toast.makeText(getContext(), "home", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.navigation_dashboard:
                    Toast.makeText(getContext(), "dashboard",                 Toast.LENGTH_SHORT).show();
                    break;
                case R.id.navigation_notifications:
                    Toast.makeText(getContext(), "notifications",          Toast.LENGTH_SHORT).show();
                    break;
            }
            return super.onOptionsItemSelected(item);
        }
    

另外趣些,還可以通過調(diào)用 registerForContextMenu()仿荆,在片段布局中注冊一個(gè)視圖來提供上下文菜單。用戶打開上下文菜單時(shí)坏平,片段會收到對 onCreateContextMenu() 的調(diào)用拢操。當(dāng)用戶選擇某個(gè)菜單項(xiàng)時(shí),片段會收到對 onContextItemSelected() 的調(diào)用舶替。

:盡管Fragment會收到與其添加的每個(gè)菜單項(xiàng)對應(yīng)的菜單項(xiàng)選定回調(diào)令境,但當(dāng)用戶選擇菜單項(xiàng)時(shí),Activity 會首先收到相應(yīng)的回調(diào)顾瞪。 如果 Activity 對菜單項(xiàng)選定回調(diào)的實(shí)現(xiàn)不會處理選定的菜單項(xiàng)舔庶,則系統(tǒng)會將事件傳遞到片段的回調(diào)。 這適用于選項(xiàng)菜單和上下文菜單陈醒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惕橙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子钉跷,更是在濱河造成了極大的恐慌弥鹦,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爷辙,死亡現(xiàn)場離奇詭異彬坏,居然都是意外死亡朦促,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門栓始,熙熙樓的掌柜王于貴愁眉苦臉地迎上來务冕,“玉大人,你說我怎么就攤上這事混滔∪骶危” “怎么了歹颓?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵坯屿,是天一觀的道長。 經(jīng)常有香客問我巍扛,道長领跛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任撤奸,我火速辦了婚禮吠昭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘胧瓜。我一直安慰自己矢棚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布府喳。 她就那樣靜靜地躺著蒲肋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钝满。 梳的紋絲不亂的頭發(fā)上兜粘,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機(jī)與錄音弯蚜,去河邊找鬼孔轴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛碎捺,可吹牛的內(nèi)容都是我干的路鹰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼收厨,長吁一口氣:“原來是場噩夢啊……” “哼悍引!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起帽氓,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤趣斤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后黎休,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浓领,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡玉凯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了联贩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漫仆。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖泪幌,靈堂內(nèi)的尸體忽然破棺而出盲厌,到底是詐尸還是另有隱情,我是刑警寧澤祸泪,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布吗浩,位于F島的核電站,受9級特大地震影響没隘,放射性物質(zhì)發(fā)生泄漏懂扼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一右蒲、第九天 我趴在偏房一處隱蔽的房頂上張望阀湿。 院中可真熱鬧,春花似錦瑰妄、人聲如沸陷嘴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灾挨。三九已至,卻和暖如春眶诈,著一層夾襖步出監(jiān)牢的瞬間涨醋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工逝撬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浴骂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓宪潮,卻偏偏與公主長得像溯警,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子狡相,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Fragment 表示 Activity中的行為或用戶界面部分梯轻。您可以將多個(gè)片段組合在一個(gè) Activity 中來...
    鹿小純0831閱讀 403評論 0 0
  • 片段 Fragment表示 Activity中的行為或用戶界面部分。您可以將多個(gè)片段組合在一個(gè) Activity ...
    岳小川閱讀 789評論 0 3
  • 參考書籍:《第一行代碼》 第二版 郭霖如有錯(cuò)漏尽棕,請批評指出喳挑! Activity 定義:Activity是Andro...
    CCCode1997閱讀 1,139評論 0 5
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 6,358評論 0 17
  • 第一個(gè)12歲的孩子 語言智能 培養(yǎng)閱讀習(xí)慣:家里閱讀氛圍,外界好玩 的閱讀環(huán)境伊诵,例書店单绑,圖書館 繪畫:體驗(yàn)顏色,結(jié)...
    婷婷_409c閱讀 174評論 0 2