fragment不重新例項化
關於Fragment
在這簡單說一下Fragment,Fragment是Android 3.0以後才出現的,是為了適應不同的手機螢幕、平板和電視機的螢幕的。另外還有一個重要的原因,因為Activity的建立到銷燬需要費時費記憶體,大量的Activity之間的跳轉會造成堆疊飽滿,引發程式崩潰或者無響應。為了解決這個問題,Fragment就產生了。Fragment是通過Activity的FragmentManager管理的,並且一個Activity可以管理多個Fragment,有效的解決了大量Activity造成的堆疊飽滿問題。現在幾乎每一個安卓App裡面都用到了Fragment。
動態新增Fragment
首先你要有一個Fragment的載體,我是用幀佈局FrameLayout作為載體。
佈局檔案:
avtivity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width ="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.sonnyzoom.fragmentdemo.MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height ="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3"
android:background="#CEE"
android:orientation="vertical">
<Button
android:id="@+id/btn_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="one" />
<Button
android:id="@+id/btn_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="two" />
</LinearLayout>
<FrameLayout
android:id="@+id/content"
android:background="#EEE"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
然後在Activity中:
FragmentManager fragmentManager=getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content,new FragmentOne()).commit();
這樣就可以把Fragment動態新增到佈局裡面了。我們看一下效果:
重新例項化.gif
大家有沒有發現,原來的Fragment裡的資料會隨著Fragment的切換而丟失了,也就是切換Fragment後再切換回來的話,前一個Fragment會被重新例項化,當然介面的資料也沒了。為什麼呢?重點來了。
解決Fragment重新例項化
如果每切換一次就例項化一次的話,FragmentManager管理下的棧也會爆滿,最終會導致手機卡頓,這很明顯不是正確的Fragment使用姿勢。正確的姿勢是使用Fragment提供的事務FragmentTransaction,然後用add的方法,而不是每次都用replace。
獲取FragmentTransaction物件:
FragmentTransaction ft=fragmentManager.beginTransaction();
然後判斷一下Fragment物件是否為空,不為空的話就用ft的hide方法把Fragment隱藏起來。不然會出現佈局重疊的情況。
public void hideFragment(FragmentTransaction ft){
//如果不為空,就先隱藏起來
if (oneFm!=null){
ft.hide(oneFm);
}
if(twoFm!=null) {
ft.hide(twoFm);
}
}
接著用ft的show方法將Fragment顯示出來:
/**
* 如果Fragment為空,就新建一個例項
* 如果不為空,就將它從棧中顯示出來
*/
if (oneFm==null){
oneFm=new FragmentOne();
ft.add(R.id.content,oneFm);
}else {
ft.show(oneFm);
}
好了,我們看一下效果:
解決重新例項化.gif
是不是完美解決了問題?下面貼出整個MainActivity的程式碼:
MainActivity.java
package com.sonnyzoom.fragmentdemo;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Toolbar toolbar;
private Button btnOne,btnTwo;
public FragmentManager fragmentManager;
private FragmentOne oneFm;
private FragmentTwo twoFm;
public static final int FRAGMENT_ONE=0;
public static final int FRAGMENT_TWO=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar= (Toolbar) findViewById(R.id.toolBar);
setSupportActionBar(toolbar);
fragmentManager=getSupportFragmentManager();
showFragment(FRAGMENT_ONE);
btnOne= (Button) findViewById(R.id.btn_one);
btnTwo= (Button) findViewById(R.id.btn_two);
btnOne.setOnClickListener(this);
btnTwo.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_one:
showFragment(FRAGMENT_ONE);
break;
case R.id.btn_two:
showFragment(FRAGMENT_TWO);
break;
}
}
public void showFragment(int index){
FragmentTransaction ft=fragmentManager.beginTransaction();
hideFragment(ft);
switch (index){
case FRAGMENT_ONE:
toolbar.setTitle("One");
/**
* 如果Fragment為空,就新建一個例項
* 如果不為空,就將它從棧中顯示出來
*/
if (oneFm==null){
oneFm=new FragmentOne();
ft.add(R.id.content,oneFm);
}else {
ft.show(oneFm);
}
break;
case FRAGMENT_TWO:
toolbar.setTitle("Two");
點選開啟連結if (twoFm==null){
twoFm=new FragmentTwo();
ft.add(R.id.content,twoFm);
}else {
ft.show(twoFm);
}
break;
}
ft.commit();
}
public void hideFragment(FragmentTransaction ft){
//如果不為空,就先隱藏起來
if (oneFm!=null){
ft.hide(oneFm);
}
if(twoFm!=null) {
ft.hide(twoFm);
}
}
}
文/backkomyoung(簡書作者)
原文連結:http://www.jianshu.com/p/91fa45c10eb7
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。