Fragment上篇
1、Fragment的生命週期
Fragment必須是依存與Activity而存在的,因此Activity的生命週期會直接影響到Fragment的生命週期。官網這張圖很好的說明了兩者生命週期的關係:
2.Fragment家族常用的API
Fragment常用的三個類:
android.app.Fragment 主要用於定義Fragment
android.app.FragmentManager 主要用於在Activity中操作Fragment
android.app.FragmentTransaction 保證一些列Fragment操作的原子性,熟悉事務這個詞,一定能明白~
a、獲取FragmentManager的方式:
getFragmentManager() // v4中,getSupportFragmentManager
b、主要的操作都是FragmentTransaction的方法
FragmentTransaction transaction = fm.benginTransatcion();//開啓一個事務
transaction.add()
往Activity中添加一個Fragment
transaction.remove()
從Activity中移除一個Fragment,如果被移除的Fragment沒有添加到回退棧(回退棧後面會詳細說),這個Fragment實例將會被銷燬。
transaction.replace()
使用另一個Fragment替換當前的,實際上就是remove()然後add()的合體~
transaction.hide()
隱藏當前的Fragment,僅僅是設爲不可見,並不會銷燬
transaction.show()
顯示之前隱藏的Fragment
detach()
會將view從UI中移除,和remove()不同,此時fragment的狀態依然由FragmentManager維護。
attach()
重建view視圖,附加到UI上並顯示。
transatcion.commit()//提交一個事務
注意:常用Fragment的哥們,可能會經常遇到這樣Activity狀態不一致:State loss這樣的錯誤。主要是因爲:commit方法一定要在Activity.onSaveInstance()之前調用。
上述,基本是操作Fragment的所有的方式了,在一個事務開啓到提交可以進行多個的添加、移除、替換等操作。
值得注意的是:如果你喜歡使用Fragment,一定要清楚這些方法,哪個會銷燬視圖,哪個會銷燬實例,哪個僅僅只是隱藏,這樣才能更好的使用它們。
a、比如:我在FragmentA中的EditText填了一些數據,當切換到FragmentB時,如果希望會到A還能看到數據,則適合你的就是hide和show;也就是說,希望保留用戶操作的面板,你可以使用hide和show,當然了不要使勁在那new實例,進行下非null判斷。
b、再比如:我不希望保留用戶操作,你可以使用remove(),然後add();或者使用replace()這個和remove,add是相同的效果。
c、remove和detach有一點細微的區別,在不考慮回退棧的情況下,remove會銷燬整個Fragment實例,而detach則只是銷燬其視圖結構,實例並不會被銷燬。那麼二者怎麼取捨使用呢?如果你的當前Activity一直存在,那麼在不希望保留用戶操作的時候,你可以優先使用detach。
上述已經介紹完成了Fragment常用的一些方法,相信看完,大家一定清楚了Fragment的產生理由,以及如何使用Fragment,再根據API的講解,也能明白,曾經爲何覺得Fragment會出現一些列亂七八槽的問題,終究是因爲沒有弄清楚其生命週期。
本篇將介紹上篇博客提到的:如何管理Fragment回退棧,Fragment如何與Activity交互,Fragment與Activity交互的最佳實踐,沒有視圖的Fragment的用處,使用Fragment創建對話框,如何與ActionBar,MenuItem集成等~~
1、管理Fragment回退棧
類似與Android系統爲Activity維護一個任務棧,我們也可以通過Activity維護一個回退棧來保存每次Fragment事務發生的變化。如果你將Fragment任務添加到回退棧,當用戶點擊後退按鈕時,將看到上一次的保存的Fragment。一旦Fragment完全從後退棧中彈出,用戶再次點擊後退鍵,則退出當前Activity。
看這樣一個效果圖:
點擊第一個按鈕,切換到第二個界面,點擊第二個按鈕,切換到第三個界面,然後點擊Back鍵依次回退。這像不像初學Android時的Activity跳轉,當然了,這裏肯定不是,不然我就跪了。這裏是Fragment實現的,用戶點擊Back,實際是Fragment回退棧不斷的彈棧。
如何添加一個Fragment事務到回退棧:
FragmentTransaction.addToBackStack(String)
下面講解代碼:很明顯一共是3個Fragment和一個Activity.
先看Activity的佈局文件:
- <RelativeLayout 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" >
- <FrameLayout
- android:id="@+id/id_content"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- </FrameLayout>
- </RelativeLayout>
<RelativeLayout 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" > <FrameLayout android:id="@+id/id_content" android:layout_width="fill_parent" android:layout_height="fill_parent" > </FrameLayout> </RelativeLayout>不同的Fragment就在這個FrameLayout中顯示。
MainActivity.java
- package com.zhy.zhy_fragments;
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.view.Window;
- public class MainActivity extends Activity
- {
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.add(R.id.id_content, new FragmentOne(),"ONE");
- tx.commit();
- }
- }
package com.zhy.zhy_fragments; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.Window; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.add(R.id.id_content, new FragmentOne(),"ONE"); tx.commit(); } }很簡單,直接將FragmentOne添加到佈局文件中的FrameLayout中,注意這裏並沒有調用FragmentTransaction.addToBackStack(String),因爲我不喜歡在當前顯示時,點擊Back鍵出現白板。而是正確的相應Back鍵,即退出我們的Activity.
下面是FragmentOne
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.Button;
- public class FragmentOne extends Fragment implements OnClickListener
- {
- private Button mBtn;
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- View view = inflater.inflate(R.layout.fragment_one, container, false);
- mBtn = (Button) view.findViewById(R.id.id_fragment_one_btn);
- mBtn.setOnClickListener(this);
- return view;
- }
- @Override
- public void onClick(View v)
- {
- FragmentTwo fTwo = new FragmentTwo();
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.replace(R.id.id_content, fTwo, "TWO");
- tx.addToBackStack(null);
- tx.commit();
- }
- }
package com.zhy.zhy_fragments; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; public class FragmentOne extends Fragment implements OnClickListener { private Button mBtn; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_one, container, false); mBtn = (Button) view.findViewById(R.id.id_fragment_one_btn); mBtn.setOnClickListener(this); return view; } @Override public void onClick(View v) { FragmentTwo fTwo = new FragmentTwo(); FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.replace(R.id.id_content, fTwo, "TWO"); tx.addToBackStack(null); tx.commit(); } }
我們在點擊FragmentOne中的按鈕時,使用了replace方法,如果你看了前一篇博客,一定記得replace是remove和add的合體,並且如果不添加事務到回退棧,前一個Fragment實例會被銷燬。這裏很明顯,我們調用tx.addToBackStack(null);將當前的事務添加到了回退棧,所以FragmentOne實例不會被銷燬,但是視圖層次依然會被銷燬,即會調用onDestoryView和onCreateView,證據就是:仔細看上面的效果圖,我們在跳轉前在文本框輸入的內容,在用戶Back得到第一個界面的時候不見了。
接下來FragmentTwo
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.Button;
- public class FragmentTwo extends Fragment implements OnClickListener
- {
- private Button mBtn ;
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- View view = inflater.inflate(R.layout.fragment_two, container, false);
- mBtn = (Button) view.findViewById(R.id.id_fragment_two_btn);
- mBtn.setOnClickListener(this);
- return view ;
- }
- @Override
- public void onClick(View v)
- {
- FragmentThree fThree = new FragmentThree();
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.hide(this);
- tx.add(R.id.id_content , fThree, "THREE");
- // tx.replace(R.id.id_content, fThree, "THREE");
- tx.addToBackStack(null);
- tx.commit();
- }
- }
package com.zhy.zhy_fragments; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; public class FragmentTwo extends Fragment implements OnClickListener { private Button mBtn ; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_two, container, false); mBtn = (Button) view.findViewById(R.id.id_fragment_two_btn); mBtn.setOnClickListener(this); return view ; } @Override public void onClick(View v) { FragmentThree fThree = new FragmentThree(); FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.hide(this); tx.add(R.id.id_content , fThree, "THREE"); // tx.replace(R.id.id_content, fThree, "THREE"); tx.addToBackStack(null); tx.commit(); } }
這裏點擊時,我們沒有使用replace,而是先隱藏了當前的Fragment,然後添加了FragmentThree的實例,最後將事務添加到回退棧。這樣做的目的是爲了給大家提供一種方案:如果不希望視圖重繪該怎麼做,請再次仔細看效果圖,我們在FragmentTwo的EditText填寫的內容,用戶Back回來時,數據還在~~~
最後FragmentThree就是簡單的Toast了:
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.Button;
- import android.widget.Toast;
- public class FragmentThree extends Fragment implements OnClickListener
- {
- private Button mBtn;
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- View view = inflater.inflate(R.layout.fragment_three, container, false);
- mBtn = (Button) view.findViewById(R.id.id_fragment_three_btn);
- mBtn.setOnClickListener(this);
- return view;
- }
- @Override
- public void onClick(View v)
- {
- Toast.makeText(getActivity(), " i am a btn in Fragment three",
- Toast.LENGTH_SHORT).show();
- }
- }
package com.zhy.zhy_fragments; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.Toast; public class FragmentThree extends Fragment implements OnClickListener { private Button mBtn; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_three, container, false); mBtn = (Button) view.findViewById(R.id.id_fragment_three_btn); mBtn.setOnClickListener(this); return view; } @Override public void onClick(View v) { Toast.makeText(getActivity(), " i am a btn in Fragment three", Toast.LENGTH_SHORT).show(); } }
好了,經過上面的介紹,應該已經知道Fragment回退棧是怎麼一回事了,以及hide,replace等各自的應用的場景。
這裏極其注意一點:上面的整體代碼不具有任何參考價值,純粹爲了顯示回退棧,在後面講解了Fragment與Activity通信以後,會重構上面的代碼!
因爲所有的Fragment都是依附於Activity的,所以通信起來並不複雜,大概歸納爲:
a、如果你Activity中包含自己管理的Fragment的引用,可以通過引用直接訪問所有的Fragment的public方法
b、如果Activity中未保存任何Fragment的引用,那麼沒關係,每個Fragment都有一個唯一的TAG或者ID,可以通過getFragmentManager.findFragmentByTag()或者findFragmentById()獲得任何Fragment實例,然後進行操作。
c、在Fragment中可以通過getActivity得到當前綁定的Activity的實例,然後進行操作。
注:如果在Fragment中需要Context,可以通過調用getActivity(),如果該Context需要在Activity被銷燬後還存在,則使用getActivity().getApplicationContext()。
因爲要考慮Fragment的重複使用,所以必須降低Fragment與Activity的耦合,而且Fragment更不應該直接操作別的Fragment,畢竟Fragment操作應該由它的管理者Activity來決定。
下面我通過兩種方式的代碼,分別重構,FragmentOne和FragmentTwo的點擊事件,以及Activity對點擊事件的響應:
首先看FragmentOne
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.Button;
- public class FragmentOne extends Fragment implements OnClickListener
- {
- private Button mBtn;
- /**
- * 設置按鈕點擊的回調
- * @author zhy
- *
- */
- public interface FOneBtnClickListener
- {
- void onFOneBtnClick();
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- View view = inflater.inflate(R.layout.fragment_one, container, false);
- mBtn = (Button) view.findViewById(R.id.id_fragment_one_btn);
- mBtn.setOnClickListener(this);
- return view;
- }
- /**
- * 交給宿主Activity處理,如果它希望處理
- */
- @Override
- public void onClick(View v)
- {
- if (getActivity() instanceof FOneBtnClickListener)
- {
- ((FOneBtnClickListener) getActivity()).onFOneBtnClick();
- }
- }
- }
package com.zhy.zhy_fragments; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; public class FragmentOne extends Fragment implements OnClickListener { private Button mBtn; /** * 設置按鈕點擊的回調 * @author zhy * */ public interface FOneBtnClickListener { void onFOneBtnClick(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_one, container, false); mBtn = (Button) view.findViewById(R.id.id_fragment_one_btn); mBtn.setOnClickListener(this); return view; } /** * 交給宿主Activity處理,如果它希望處理 */ @Override public void onClick(View v) { if (getActivity() instanceof FOneBtnClickListener) { ((FOneBtnClickListener) getActivity()).onFOneBtnClick(); } } }
可以看到現在的FragmentOne不和任何Activity耦合,任何Activity都可以使用;並且我們聲明瞭一個接口,來回調其點擊事件,想要管理其點擊事件的Activity實現此接口就即可。可以看到我們在onClick中首先判斷了當前綁定的Activity是否實現了該接口,如果實現了則調用。
再看FragmentTwo
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.Button;
- public class FragmentTwo extends Fragment implements OnClickListener
- {
- private Button mBtn ;
- private FTwoBtnClickListener fTwoBtnClickListener ;
- public interface FTwoBtnClickListener
- {
- void onFTwoBtnClick();
- }
- //設置回調接口
- public void setfTwoBtnClickListener(FTwoBtnClickListener fTwoBtnClickListener)
- {
- this.fTwoBtnClickListener = fTwoBtnClickListener;
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- View view = inflater.inflate(R.layout.fragment_two, container, false);
- mBtn = (Button) view.findViewById(R.id.id_fragment_two_btn);
- mBtn.setOnClickListener(this);
- return view ;
- }
- @Override
- public void onClick(View v)
- {
- if(fTwoBtnClickListener != null)
- {
- fTwoBtnClickListener.onFTwoBtnClick();
- }
- }
- }
package com.zhy.zhy_fragments; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; public class FragmentTwo extends Fragment implements OnClickListener { private Button mBtn ; private FTwoBtnClickListener fTwoBtnClickListener ; public interface FTwoBtnClickListener { void onFTwoBtnClick(); } //設置回調接口 public void setfTwoBtnClickListener(FTwoBtnClickListener fTwoBtnClickListener) { this.fTwoBtnClickListener = fTwoBtnClickListener; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_two, container, false); mBtn = (Button) view.findViewById(R.id.id_fragment_two_btn); mBtn.setOnClickListener(this); return view ; } @Override public void onClick(View v) { if(fTwoBtnClickListener != null) { fTwoBtnClickListener.onFTwoBtnClick(); } } }
與FragmentOne極其類似,但是我們提供了setListener這樣的方法,意味着Activity不僅需要實現該接口,還必須顯示調用mFTwo.setfTwoBtnClickListener(this)。
最後看Activity :
- package com.zhy.zhy_fragments;
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.view.Window;
- import com.zhy.zhy_fragments.FragmentOne.FOneBtnClickListener;
- import com.zhy.zhy_fragments.FragmentTwo.FTwoBtnClickListener;
- public class MainActivity extends Activity implements FOneBtnClickListener,
- FTwoBtnClickListener
- {
- private FragmentOne mFOne;
- private FragmentTwo mFTwo;
- private FragmentThree mFThree;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- mFOne = new FragmentOne();
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.add(R.id.id_content, mFOne, "ONE");
- tx.commit();
- }
- /**
- * FragmentOne 按鈕點擊時的回調
- */
- @Override
- public void onFOneBtnClick()
- {
- if (mFTwo == null)
- {
- mFTwo = new FragmentTwo();
- mFTwo.setfTwoBtnClickListener(this);
- }
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.replace(R.id.id_content, mFTwo, "TWO");
- tx.addToBackStack(null);
- tx.commit();
- }
- /**
- * FragmentTwo 按鈕點擊時的回調
- */
- @Override
- public void onFTwoBtnClick()
- {
- if (mFThree == null)
- {
- mFThree = new FragmentThree();
- }
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.hide(mFTwo);
- tx.add(R.id.id_content, mFThree, "THREE");
- // tx.replace(R.id.id_content, fThree, "THREE");
- tx.addToBackStack(null);
- tx.commit();
- }
- }
package com.zhy.zhy_fragments; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.Window; import com.zhy.zhy_fragments.FragmentOne.FOneBtnClickListener; import com.zhy.zhy_fragments.FragmentTwo.FTwoBtnClickListener; public class MainActivity extends Activity implements FOneBtnClickListener, FTwoBtnClickListener { private FragmentOne mFOne; private FragmentTwo mFTwo; private FragmentThree mFThree; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); mFOne = new FragmentOne(); FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.add(R.id.id_content, mFOne, "ONE"); tx.commit(); } /** * FragmentOne 按鈕點擊時的回調 */ @Override public void onFOneBtnClick() { if (mFTwo == null) { mFTwo = new FragmentTwo(); mFTwo.setfTwoBtnClickListener(this); } FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.replace(R.id.id_content, mFTwo, "TWO"); tx.addToBackStack(null); tx.commit(); } /** * FragmentTwo 按鈕點擊時的回調 */ @Override public void onFTwoBtnClick() { if (mFThree == null) { mFThree = new FragmentThree(); } FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.hide(mFTwo); tx.add(R.id.id_content, mFThree, "THREE"); // tx.replace(R.id.id_content, fThree, "THREE"); tx.addToBackStack(null); tx.commit(); } }
代碼重構結束,與開始的效果一模一樣。上面兩種通信方式都是值得推薦的,隨便選擇一種自己喜歡的。這裏再提一下:雖然Fragment和Activity可以通過getActivity與findFragmentByTag或者findFragmentById,進行任何操作,甚至在Fragment裏面操作另外的Fragment,但是沒有特殊理由是絕對不提倡的。Activity擔任的是Fragment間類似總線一樣的角色,應當由它決定Fragment如何操作。另外雖然Fragment不能響應Intent打開,但是Activity可以,Activity可以接收Intent,然後根據參數判斷顯示哪個Fragment。
運行時配置發生變化,最常見的就是屏幕發生旋轉,如果你不知道如何處理屏幕變化可以參考:Android 屏幕旋轉 處理 AsyncTask 和 ProgressDialog 的最佳方案
這裏提一下:很多人覺得強制設置屏幕的方向就可以了,但是有一點,當你的應用被至於後臺(例如用戶點擊了home),長時間沒有返回的時候,你的應用也會被重新啓動。比如上例:如果你把上面的例子你至於FragmentThree界面,然後處於後臺狀態,長時間後你會發現當你再次通過home打開時,上面FragmentThree與FragmentOne疊加在一起,這就是因爲你的Activity重新啓動,在原來的FragmentThree上又繪製了一個FragmentOne。
好了,下面看一段代碼:
Activity:
- package com.zhy.zhy_fragments;
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.view.Window;
- public class MainActivity extends Activity
- {
- private FragmentOne mFOne;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- mFOne = new FragmentOne();
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.add(R.id.id_content, mFOne, "ONE");
- tx.commit();
- }
- }
package com.zhy.zhy_fragments; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.Window; public class MainActivity extends Activity { private FragmentOne mFOne; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); mFOne = new FragmentOne(); FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.add(R.id.id_content, mFOne, "ONE"); tx.commit(); } }
Fragment
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- public class FragmentOne extends Fragment
- {
- private static final String TAG = "FragmentOne";
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- Log.e(TAG, "onCreateView");
- View view = inflater.inflate(R.layout.fragment_one, container, false);
- return view;
- }
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- Log.e(TAG, "onCreate");
- }
- @Override
- public void onDestroyView()
- {
- // TODO Auto-generated method stub
- super.onDestroyView();
- Log.e(TAG, "onDestroyView");
- }
- @Override
- public void onDestroy()
- {
- // TODO Auto-generated method stub
- super.onDestroy();
- Log.e(TAG, "onDestroy");
- }
- }
package com.zhy.zhy_fragments; import android.app.Fragment; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class FragmentOne extends Fragment { private static final String TAG = "FragmentOne"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.e(TAG, "onCreateView"); View view = inflater.inflate(R.layout.fragment_one, container, false); return view; } @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); Log.e(TAG, "onCreate"); } @Override public void onDestroyView() { // TODO Auto-generated method stub super.onDestroyView(); Log.e(TAG, "onDestroyView"); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.e(TAG, "onDestroy"); } }
很簡單的代碼,當你運行之後,不斷的旋轉屏幕,你會發現每旋轉一次屏幕,屏幕上就多了一個FragmentOne的實例,並且後臺log會打印出許多套生命週期的回調。
類似:
- 07-20 08:18:46.651: E/FragmentOne(1633): onCreate
- 07-20 08:18:46.651: E/FragmentOne(1633): onCreate
- 07-20 08:18:46.651: E/FragmentOne(1633): onCreate
- 07-20 08:18:46.681: E/FragmentOne(1633): onCreateView
- 07-20 08:18:46.831: E/FragmentOne(1633): onCreateView
- 07-20 08:18:46.891: E/FragmentOne(1633): onCreateView
07-20 08:18:46.651: E/FragmentOne(1633): onCreate 07-20 08:18:46.651: E/FragmentOne(1633): onCreate 07-20 08:18:46.651: E/FragmentOne(1633): onCreate 07-20 08:18:46.681: E/FragmentOne(1633): onCreateView 07-20 08:18:46.831: E/FragmentOne(1633): onCreateView 07-20 08:18:46.891: E/FragmentOne(1633): onCreateView
這是爲什麼呢,因爲當屏幕發生旋轉,Activity發生重新啓動,默認的Activity中的Fragment也會跟着Activity重新創建;這樣造成當旋轉的時候,本身存在的Fragment會重新啓動,然後當執行Activity的onCreate時,又會再次實例化一個新的Fragment,這就是出現的原因。
那麼如何解決呢:
其實通過檢查onCreate的參數Bundle savedInstanceState就可以判斷,當前是否發生Activity的重新創建:
默認的savedInstanceState會存儲一些數據,包括Fragment的實例:通過打印可以看出:
- 07-20 08:23:12.952: E/FragmentOne(1782): Bundle[{android:fragments=android.app.FragmentManagerState@40d0b7b8, android:viewHierarchyState=Bundle[{android:focusedViewId=2131230721, android:views=android.util.SparseArray@40d0af68}]}]
07-20 08:23:12.952: E/FragmentOne(1782): Bundle[{android:fragments=android.app.FragmentManagerState@40d0b7b8, android:viewHierarchyState=Bundle[{android:focusedViewId=2131230721, android:views=android.util.SparseArray@40d0af68}]}]所以,我們簡單改一下代碼,只有在savedInstanceState==null時,才進行創建Fragment實例:
- package com.zhy.zhy_fragments;
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Window;
- public class MainActivity extends Activity
- {
- private static final String TAG = "FragmentOne";
- private FragmentOne mFOne;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- Log.e(TAG, savedInstanceState+"");
- if(savedInstanceState == null)
- {
- mFOne = new FragmentOne();
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.add(R.id.id_content, mFOne, "ONE");
- tx.commit();
- }
- }
- }
package com.zhy.zhy_fragments; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.util.Log; import android.view.Window; public class MainActivity extends Activity { private static final String TAG = "FragmentOne"; private FragmentOne mFOne; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); Log.e(TAG, savedInstanceState+""); if(savedInstanceState == null) { mFOne = new FragmentOne(); FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.add(R.id.id_content, mFOne, "ONE"); tx.commit(); } } }
現在無論進行多次旋轉都只會有一個Fragment實例在Activity中。
現在還存在一個問題,就是重新繪製時,Fragment發生重建,原本的數據如何保持?
其實和Activity類似,Fragment也有onSaveInstanceState的方法,在此方法中進行保存數據,然後在onCreate或者onCreateView或者onActivityCreated進行恢復都可以。
由於篇幅原因,就不貼測試代碼了。
Fragment可以添加自己的MenuItem到Activity的ActionBar或者可選菜單中。
a、在Fragment的onCreate中調用 setHasOptionsMenu(true);
b、然後在Fragment子類中實現onCreateOptionsMenu
c、如果希望在Fragment中處理MenuItem的點擊,也可以實現onOptionsItemSelected;當然了Activity也可以直接處理該MenuItem的點擊事件。
代碼:
Fragment
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.Menu;
- import android.view.MenuInflater;
- import android.view.MenuItem;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.Toast;
- public class FragmentOne extends Fragment
- {
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- View view = inflater.inflate(R.layout.fragment_one, container, false);
- return view;
- }
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
- {
- inflater.inflate(R.menu.fragment_menu, menu);
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item)
- {
- switch (item.getItemId())
- {
- case R.id.id_menu_fra_test:
- Toast.makeText(getActivity(), "FragmentMenuItem1", Toast.LENGTH_SHORT).show();
- break;
- }
- return true;
- }
- }
package com.zhy.zhy_fragments; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; public class FragmentOne extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_one, container, false); return view; } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.fragment_menu, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.id_menu_fra_test: Toast.makeText(getActivity(), "FragmentMenuItem1", Toast.LENGTH_SHORT).show(); break; } return true; } }
Activity
- package com.zhy.zhy_fragments;
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.view.Window;
- import android.widget.Toast;
- public class MainActivity extends Activity
- {
- private static final String TAG = "FragmentOne";
- private FragmentOne mFOne;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- Log.e(TAG, savedInstanceState + "");
- if (savedInstanceState == null)
- {
- mFOne = new FragmentOne();
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.add(R.id.id_content, mFOne, "ONE");
- tx.commit();
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu)
- {
- super.onCreateOptionsMenu(menu);
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item)
- {
- switch (item.getItemId())
- {
- case R.id.action_settings:
- Toast.makeText(this, "setting", Toast.LENGTH_SHORT).show();
- return true;
- default:
- //如果希望Fragment自己處理MenuItem點擊事件,一定不要忘了調用super.xxx
- return super.onOptionsItemSelected(item);
- }
- }
- }
package com.zhy.zhy_fragments; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.widget.Toast; public class MainActivity extends Activity { private static final String TAG = "FragmentOne"; private FragmentOne mFOne; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); Log.e(TAG, savedInstanceState + ""); if (savedInstanceState == null) { mFOne = new FragmentOne(); FragmentManager fm = getFragmentManager(); FragmentTransaction tx = fm.beginTransaction(); tx.add(R.id.id_content, mFOne, "ONE"); tx.commit(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_settings: Toast.makeText(this, "setting", Toast.LENGTH_SHORT).show(); return true; default: //如果希望Fragment自己處理MenuItem點擊事件,一定不要忘了調用super.xxx return super.onOptionsItemSelected(item); } } }
效果圖:
好了,可以很好的看到,Fragment可以添加MenuItem,也可以自己處理點擊~~~
沒有佈局文件Fragment實際上是爲了保存,當Activity重啓時,保存大量數據準備的
請參考博客:Android 屏幕旋轉 處理 AsyncTask 和 ProgressDialog 的最佳方案
這是Google推薦的方式,我也單獨寫過博客介紹,請參考:Android 官方推薦 : DialogFragment 創建對話框
好了,終於把Fragment相關的聯繫到一起了,上述基本包含了Fragment所有的用法~~~相信大家如果能夠看完,一定有不少的收穫~~~
有任何問題,歡迎留言~~~
兩篇結束,相信你對Fragment已經有了一定的瞭解,那麼在項目中的最佳實踐是什麼呢?請移步:Android Fragment 你應該知道的一切
一、ListFragement的介紹:
ListFragment繼承於Fragment。因此它具有Fragment的特性,能夠作爲activity中的一部分,目的也是爲了使頁面設計更加靈活。相比Fragment,ListFragment的內容是以列表(list)的形式顯示的。
1、ListFragment佈局:
ListFragment的默認佈局包含一個list view。因此,在ListFragment對應的佈局文件中,必須指定一個 android:id 爲 “@android:id/list” 的ListView控件! 若用戶想修改listview,可以在onCreateView(LayoutInflater, ViewGroup, Bundle)中進行修改。當然,用戶也可以在ListFragment的佈局中包含其它的控件。
下面是官方文檔中ListFragment對應的一個layout示例:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<ListView android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FF00"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
<TextView android:id="@id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:text="No data"/>
</LinearLayout>
ListView中每一行的顯示內容,是通過設置適配器ListAdapter來實現的。我們既可以自定義,也可以採用系統默認的layout。後面的應用實例中,會分別列舉2種情況下的顯示
2、綁定數據:
ListFragment綁定ListView的數據(即綁定適配器)時,必須通過ListFragment.setListAdapter()接口來綁定數據,而不是使用ListView.setAdapter() 或其它方法
二、通過ArrayAdapter來加載ListFragment的舉例:
【舉例】現在將平板電腦分成三部分:點擊左側的按鈕,出現中間的新聞標題列表(ListFragment),點擊中間ListFragment的某個item,在最右側的fragment中顯示詳情。
新建工程文件m01_ListFragment01:
(1)定義activity_main.xml的佈局:
activity_main.xml的代碼如下:
<LinearLayout 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"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/left"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#cccccc"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="show ListFragment" />
</LinearLayout>
<LinearLayout
android:id="@+id/center"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="#AFEEEE"
android:orientation="vertical" >
</LinearLayout>
<LinearLayout
android:id="@+id/center"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="#00FFFF"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
實際上分配了三個線性佈局,左側顯示按鈕,中間顯示標題,右側顯示詳情。這個佈局文件對應的可視化界面如下:
(2)定義中間的ListFragment,即新建文件ArticleListFragment.java:
ArticleListFragment.java的代碼如下:
1 package com.example.m01_listfragment01;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import android.app.ListFragment;
7 import android.os.Bundle;
8 import android.view.LayoutInflater;
9 import android.view.View;
10 import android.view.ViewGroup;
11 import android.widget.ArrayAdapter;
12
13 public class ArticleListFragment extends ListFragment {
14
15 private ArrayAdapter<String> adapter;
16
17 @Override
18 public void onCreate(Bundle savedInstanceState) {
19 // TODO Auto-generated method stub
20 super.onCreate(savedInstanceState);
21
22 //定義一個數組
23 List<String> data = new ArrayList<String>();
24 for (int i = 0; i < 30; i++) {
25 data.add("smyh" + i);
26 }
27 //將數組加到ArrayAdapter當中
28 adapter = new ArrayAdapter<String>(getActivity(),
29 android.R.layout.simple_list_item_1, data);
30 //綁定適配器時,必須通過ListFragment.setListAdapter()接口,而不是ListView.setAdapter()或其它方法
31 setListAdapter(adapter);
32 }
33
34 @Override
35 public View onCreateView(LayoutInflater inflater, ViewGroup container,
36 Bundle savedInstanceState) {
37 // TODO Auto-generated method stub
38 return super.onCreateView(inflater, container, savedInstanceState);
39 }
40
41 @Override
42 public void onPause() {
43 // TODO Auto-generated method stub
44 super.onPause();
45 }
46 }
核心代碼是22至32行:我們讓這個Fragment繼承ListFragment,然後在onCreate()方法中定義一個ArrayAdapter,將數據放進去,最後綁定適配器就行了。需要注意的是,由於我們繼承的是ListFragment,這個Fragment默認自帶了一個佈局,所以我們不需要重新新建佈局文件了。
(3)將中間的ListFragment加載到Activity當中去。當我們點擊按鈕時,就開始加載這個Fragment:
MainActivity.java的代碼如下:
1 package com.example.m01_listfragment01;
2
3 import android.app.Activity;
4 import android.app.FragmentManager;
5 import android.app.FragmentTransaction;
6 import android.os.Bundle;
7 import android.view.Menu;
8 import android.view.View;
9 import android.view.View.OnClickListener;
10 import android.widget.Button;
11
12 public class MainActivity extends Activity {
13
14 private FragmentManager manager;
15 private FragmentTransaction transaction;
16 @Override
17 protected void onCreate(Bundle savedInstanceState) {
18 super.onCreate(savedInstanceState);
19 setContentView(R.layout.activity_main);
20 Button button = (Button) findViewById(R.id.button1);
21 button.setOnClickListener(new OnClickListener() {
22
23 //點擊按鈕,加載ListFragment
24 @Override
25 public void onClick(View v) {
26 // TODO Auto-generated method stub
27 manager = getFragmentManager();
28 transaction = manager.beginTransaction();
29 ArticleListFragment articleListFragment = new ArticleListFragment();
30 transaction.add(R.id.center, articleListFragment, "article");
31 transaction.commit();
32 }
33 });
34
35 }
36
37 @Override
38 public boolean onCreateOptionsMenu(Menu menu) {
39 // Inflate the menu; this adds items to the action bar if it is present.
40 getMenuInflater().inflate(R.menu.main, menu);
41 return true;
42 }
43 }
這個代碼比較簡單,就不多解釋了。
現在運行程序,初始界面如下:
點擊左側的按鈕後,顯示如下:
注:如果想實現:點擊中間的某個item,彈出吐司顯示那個item中的內容,可以在上方的ArticleListFragment.java中的監聽事件裏添加如下代碼:
(代碼放置的位置是:讓它和Fragment的生命週期方法並列就行了)
1 @Override
2 public void onListItemClick(ListView l, View v, int position, long id) {
3 // TODO Auto-generated method stub
4 super.onListItemClick(l, v, position, id);
5 String item = adapter.getItem(position);
6 Toast.makeText(getActivity(), item, 1).show();
7 }
由此我們可以看到,監聽事件的函數爲onListItemClick(),可以直接寫,不需要set。
這裏面關鍵代碼在第05行,通過getItem()接收那個item,然後用字符串來接收。
我們先去掉這部分的監聽事件代碼,繼續往下看。
(4)點擊中間ListFragment的item,加載右邊的DetailFragment:
我們在中間ListFragment中添加一個按鈕的監聽事件,監聽事件的函數爲onListItemClick(),ArticleListFragment.java在上面代碼的基礎之上,添加的代碼如下:
(代碼放置的位置是:讓它和Fragment的生命週期方法並列就行了)
1 //點擊按鈕,加載最右側的Fragment
2 @Override
3 public void onListItemClick(ListView l, View v, int position, long id) {
4 // TODO Auto-generated method stub
5 super.onListItemClick(l, v, position, id);
6
7 //點擊按鈕後,加載右邊的Fragment
8 FragmentManager manager = getFragmentManager();
9 FragmentTransaction transaction = manager.beginTransaction();
10 DetailFragment detailFragment = new DetailFragment();
11 //記住:這個地方必須用replace,而不是用add
12 transaction.replace(R.id.right, detailFragment, "detailFragment");
13
14 //將中間的item的內容放到Bundle對象當中,然後放到最右側Frament的參數當中
15 String item = adapter.getItem(position);
16 Bundle args = new Bundle();
17 args.putString("item",item);
18 detailFragment.setArguments(args);
19 //Toast.makeText(getActivity(), item, 1).show();
20
21 transaction.commit();
22 }
上面的代碼中,我們是在中間的Fragment中點擊按鈕,然後加載右邊的Fragment,然後要注意14至18行的核心代碼,看一下它是如何通過bundle來傳遞數據的。
需要注意的是,第12行代碼必須用replace的方式加載右側的fragment,而不是add;如果用add,運行的錯誤稍後將展示出來。
(5)定義右邊的DetailFragment:
先定義佈局文件,在裏面加一個TextView,fragment_detail.xml的代碼如下:
<?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:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
然後新建文件,DetailFragment.java的代碼如下:
package com.example.m01_listfragment01;
1 package com.example.m01_listfragment01;
2
3 import android.app.Fragment;
4 import android.os.Bundle;
5 import android.view.LayoutInflater;
6 import android.view.View;
7 import android.view.ViewGroup;
8 import android.widget.TextView;
9
10 public class DetailFragment extends Fragment {
11
12
13 @Override
14 public void onCreate(Bundle savedInstanceState) {
15 // TODO Auto-generated method stub
16 super.onCreate(savedInstanceState);
17 }
18
19 @Override
20 public View onCreateView(LayoutInflater inflater, ViewGroup container,
21 Bundle savedInstanceState) {
22 // TODO Auto-generated method stub
23 View view = inflater.inflate(R.layout.fragment_detail, null);
24 TextView textView = (TextView)view.findViewById(R.id.textView1);
25 textView.setText(""+getArguments().getString("item"));
26 return view;
27 }
28
29 @Override
30 public void onPause() {
31 // TODO Auto-generated method stub
32 super.onPause();
33 }
34 }
核心代碼是第25行,仔細看一下我們是怎麼通過鍵值對來拿到中間的Fragment傳遞過來的item的內容。
現在運行程序,一次點擊左邊的按鈕和中間的item,效果如下:
如果我們在中間的Fragment中錯誤地通過add方式加載右邊的Fragment,而不是通過replace方式,最終錯誤的效果如下:
也就是說,每點擊一次中間的item,就會在右邊繼續加載一個文本,而不是替代的方式,很顯然,這種方式不是我們想要的。