這裏使用v4.app.Fragment ,因爲他兼容更低版本 ,他需要你的Activity繼承FragmentActivity而不是Activity ,除非你使用的是app.Fragmetn,app.Fragment兼容的最低版本爲3.0。
Fragmetn生命週期
先看下Fragment的生命週期:
下面用代碼說話:
public class FragmentA extends android.support.v4.app.Fragment{
/**
* 當Fragment與Activity發生關聯時調用。
*
* @param context 當前Activity的Context
*/
@Override
public void onAttach(Context context) {
super.onAttach(context);
L("onAttach");
}
/**
* 在創建fragment時系統會調用此方法。
* 在實現代碼中,你可以初始化想要在fragment中保持的那些必要組件(這裏的組件是指除了view之外的東西,比如需要進行界面展示的關鍵數據)
* 當fragment處於暫停或者停止狀態之後可重新啓用它們。
*
* @param savedInstanceState 如果你在onSaveInstanceState()將一些值保存到了Bundle中,在這裏你可以拿到他
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String aaa = "";
if (savedInstanceState != null)
aaa = savedInstanceState.getString("aaa");
L("onCreate _ " + aaa);
}
/**
* 在第一次爲fragment繪製用戶界面時系統會調用此方法
* 爲fragment繪製用戶界面,這個函數必須要返回所繪出的fragment的根View
* 如果fragment沒有用戶界面可以返回空。
*
* @param inflater 用來填充的Layout
* @param container 父容器
* @param savedInstanceState 如果你在onSaveInstanceState()將一些值保存到了Bundle中,在這裏你可以拿到他
* @return
*/
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
String aaa = "";
if (savedInstanceState != null)
aaa = savedInstanceState.getString("aaa");
L("onCreateView _ " + aaa);
return inflater.inflate(R.layout.fragment_a , container , false);
}
/**
* 當Activity的onCreate方法返回時調用
*
* @param savedInstanceState 如果你在onSaveInstanceState()將一些值保存到了Bundle中,在這裏你可以拿到他
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String aaa = "";
if (savedInstanceState != null)
aaa = savedInstanceState.getString("aaa");
L("onActivityCreated _ " + aaa);
}
/**
* 將當前Fragment切到後臺再切回來的時候,如果這期間時間不長,他將會被第一個調用
*/
@Override
public void onStart() {
super.onStart();
L("onStart");
}
/**
* 將當前Fragment切到後臺再切回來的時候,如果這期間時間不長,他將會被第二個調用
*/
@Override
public void onResume() {
super.onResume();
L("onResume");
}
/**
* 系統回調用該函數作爲用戶離開fragment的第一個預兆(儘管這並不總意味着fragment被銷燬)
* 在當前用戶會話結束之前,通常要在這裏提交任何應該持久化的變化(因爲用戶可能不再返回)。
*/
@Override
public void onPause() {
super.onPause();
L("onPause");
}
/**
* 在onPause之後調用,在這裏你可以將當前Fragment的狀態保存下來,
* 因爲用戶可能會在這個Fragment被回收之後纔回來,爲了確保他們回來後看到的界面依然是離開前的樣子
* 你需要保存一些數據信息到Bundle,並在onCreateView()中重新設置到界面上
* @param outState
*/
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("aaa", "FragmentA_Bundle");
L("onSaveInstanceState");
}
/**
* 半死不活
*/
@Override
public void onStop() {
super.onStop();
L("onStop");
}
/**
* 這個還不太明白什麼意思……
*/
@Override
public void onDestroyView() {
super.onDestroyView();
L("onDestroyView");
}
/**
* 這個Fragment已經死透了
*/
@Override
public void onDestroy() {
super.onDestroy();
L("onDestroy");
}
/**
* 這個Fragment已經跟Activity斷絕關係了
*/
@Override
public void onDetach() {
super.onDetach();
L("onDetach");
}
/**
* 這是個LOG……
* @param msg 你想說的話……
*/
private void L(String msg){
Log.i("FragmentTag" , "FragmentA : " + msg);
}
}
我將每一個生命週期的回調都打上了LOG。然後我是這麼操作的:打開App,Fragment一張傻臉呈現在我面前,然後我趕緊按返回鍵退出App。LOG信息就是下面這樣了。
onAttach
onCreate
onCreateView
onActivityCreated
onStart
onResume
onPause
onSaveInstanceState
onStop
onDestroyView
onDestroy
onDetach
具體每個回調的調用時機,都在註釋中。這裏要說的是, 如果你看到Fragment的傻臉時候按Home鍵,他會調用onPause ,onSaveInstanceState , onStop , 然後再回到他那張傻臉的時候會調用onStart , onResume。如果在這期間作了別的操作,比如說瀏覽了一些黃圖,搖了幾個妹子,然後再回來他大概已經被回收了,這時他會調用onCreate,onCreateView,onActivityCreated,onStart,onResume,我理解的是你可以在onCreateView()中通過Bundle將界面恢復到用戶離開之前的樣子。
Fragment切換
對Fragment的管理,中國人兒歪果仁兒都使用FragmentManager,通過他可以得到一個FragmentTransaction,字面意思就是事務,在對Fragment做了一系列操作後,提交事務你的操作就會或報錯或改變或沒反應的在屏幕上應驗。
首先要了解一下FragmentTransaction的這4個方法:
add() 添加
replace() 替換
hide() 隱藏
show() 顯示
英語6級不黑不吹~這裏先這樣,後面會告訴你他們怎麼用。
這裏主要說Fragment之間的切換,兩種方式:
1 . 替換 replace()
2 . 切換 hide() add() show()
看需求而定,如果Fragment之間的切換並不是特別頻繁,那麼使用1.替換會更好一點。如果你是頻繁切換,2.切換會性能更優。
這個MainActivity中,使用了“1.替換”的方式切換Fragment:
/**
* 界面上有兩個Button
* 點擊A切換到FragmentA
* 點擊B切換到FragmentB
*/
public class MainActivity extends FragmentActivity {
Fragment fragmentA;
Fragment fragmentB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentA = new FragmentA();
fragmentB = new FragmentB();
}
/**
* ButtonA的點擊事件
* @param view
*/
public void A(View view){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.f , fragmentA).commit();
}
/**
* ButtonB的點擊事件
* @param view
*/
public void B(View view){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.f , fragmentB).commit();
}
}
打印Log,會發現切換期間兩個Fragment是在不停初始化的,也就是說,我乾死你我再站這,你再幹死我你再站這,有你沒我有我沒你。
在這個MainActivity中,使用了“2.切換”的方式在兩個Fragment之間跳轉,纏綿,周旋,遊走,並且
個人認爲這樣纔是Fragment之間切換的正確姿勢 ,當然,不同的體位是要根據不同喜好的人改變的,這裏同理,根據需求而定:
/**
* 界面上有兩個Button
* 點擊A切換到FragmentA
* 點擊B切換到FragmentB
*/
public class MainActivity extends FragmentActivity {
Fragment fragmentA;
Fragment fragmentB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentA = new FragmentA();
fragmentB = new FragmentB();
}
/**
* ButtonA的點擊事件
* @param view
*/
public void A(View view){
hideFragment();
showWhat(fragmentA);
}
/**
* ButtonB的點擊事件
* @param view
*/
public void B(View view){
hideFragment();
showWhat(fragmentB);
}
private void hideFragment(){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
if (fragmentList != null){
for (int i = 0; i < fragmentList.size(); i++) {
ft.hide(fragmentList.get(i));
}
ft.commit();
}
}
private void showWhat(Fragment fragment){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (!fragment.isAdded()){
ft.add(R.id.f, fragment);
}else{
ft.show(fragment);
}
ft.commit();
}
}
打印Log,會發現切換期間完全沒有走任何一個生命週期,除了第一次add()的時候。這就相當於你去前臺表演的時候我就去幕後了,我們輪流上臺。說到輪流,我想起了一首詩。“南村羣童欺我老無力,輪流與我發生性關係”,哈哈哈哈哈。算福利了,送給大家。
好了 基本使用就這些了,下面還會有一些別的花樣兒等着你。