關(guān)于Fragment
在這簡(jiǎn)單說(shuō)一下Fragment,F(xiàn)ragment是Android 3.0以后才出現(xiàn)的葬燎,是為了適應(yīng)不同的手機(jī)屏幕、平板和電視機(jī)的屏幕的。另外還有一個(gè)重要的原因州叠,因?yàn)锳ctivity的創(chuàng)建到銷毀需要費(fèi)時(shí)費(fèi)內(nèi)存,大量的Activity之間的跳轉(zhuǎn)會(huì)造成堆棧飽滿凶赁,引發(fā)程序崩潰或者無(wú)響應(yīng)咧栗。為了解決這個(gè)問(wèn)題,F(xiàn)ragment就產(chǎn)生了虱肄。Fragment是通過(guò)Activity的FragmentManager管理的致板,并且一個(gè)Activity可以管理多個(gè)Fragment,有效的解決了大量Activity造成的堆棧飽滿問(wèn)題∮搅現(xiàn)在幾乎每一個(gè)安卓App里面都用到了Fragment斟或。
動(dòng)態(tài)添加Fragment
首先你要有一個(gè)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動(dòng)態(tài)添加到布局里面了缕粹。我們看一下效果:
大家有沒(méi)有發(fā)現(xiàn),原來(lái)的Fragment里的數(shù)據(jù)會(huì)隨著Fragment的切換而丟失了纸淮,也就是切換Fragment后再切換回來(lái)的話平斩,前一個(gè)Fragment會(huì)被重新實(shí)例化,當(dāng)然界面的數(shù)據(jù)也沒(méi)了咽块。為什么呢绘面?重點(diǎn)來(lái)了。
解決Fragment重新實(shí)例化
如果每切換一次就實(shí)例化一次的話侈沪,F(xiàn)ragmentManager管理下的棧也會(huì)爆滿揭璃,最終會(huì)導(dǎo)致手機(jī)卡頓,這很明顯不是正確的Fragment使用姿勢(shì)亭罪。正確的姿勢(shì)是使用Fragment提供的事務(wù)FragmentTransaction瘦馍,然后用add的方法,而不是每次都用replace应役。
獲取FragmentTransaction對(duì)象:
FragmentTransaction ft=fragmentManager.beginTransaction();
然后判斷一下Fragment對(duì)象是否為空情组,不為空的話就用ft的hide方法把Fragment隱藏起來(lái)。不然會(huì)出現(xiàn)布局重疊的情況箩祥。
public void hideFragment(FragmentTransaction ft){
//如果不為空院崇,就先隱藏起來(lái)
if (oneFm!=null){
ft.hide(oneFm);
}
if(twoFm!=null) {
ft.hide(twoFm);
}
}
接著用ft的show方法將Fragment顯示出來(lái):
/**
* 如果Fragment為空,就新建一個(gè)實(shí)例
* 如果不為空袍祖,就將它從棧中顯示出來(lái)
*/
if (oneFm==null){
oneFm=new FragmentOne();
ft.add(R.id.content,oneFm);
}else {
ft.show(oneFm);
}
好了底瓣,我們看一下效果:
解決屏幕旋轉(zhuǎn)會(huì)布局重疊
據(jù)反應(yīng)上面的方法在屏幕旋轉(zhuǎn)后會(huì)發(fā)生布局重疊現(xiàn)象,其實(shí)解決這個(gè)問(wèn)題很簡(jiǎn)單蕉陋,只需記錄一下位置即可捐凭。
@Override
protected void onSaveInstanceState(Bundle outState) {
//屏幕旋轉(zhuǎn)時(shí)記錄位置
outState.putInt(POSITION, position);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
//屏幕恢復(fù)時(shí)取出位置
showFragment(savedInstanceState.getInt(POSITION));
super.onRestoreInstanceState(savedInstanceState);
}
是不是完美解決了問(wèn)題?下面貼出整個(gè)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 String POSITION = "position";
public static final int FRAGMENT_ONE=0;
public static final int FRAGMENT_TWO=1;
private int position;
@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
protected void onSaveInstanceState(Bundle outState) {
//屏幕旋轉(zhuǎn)時(shí)記錄位置
outState.putInt(POSITION, position);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
//屏幕恢復(fù)時(shí)取出位置
showFragment(savedInstanceState.getInt(POSITION));
super.onRestoreInstanceState(savedInstanceState);
}
@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);
//注意這里設(shè)置位置
position = index;
switch (index){
case FRAGMENT_ONE:
toolbar.setTitle("One");
/**
* 如果Fragment為空寺滚,就新建一個(gè)實(shí)例
* 如果不為空柑营,就將它從棧中顯示出來(lái)
*/
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){
//如果不為空,就先隱藏起來(lái)
if (oneFm!=null){
ft.hide(oneFm);
}
if(twoFm!=null) {
ft.hide(twoFm);
}
}
}
試試吧村视!
如果你還在糾結(jié)這個(gè)問(wèn)題官套,那就動(dòng)手敲一遍吧。
如果文章中有什么錯(cuò)誤的地方蚁孔,歡迎在評(píng)論下方留言奶赔!