Fragment的產(chǎn)生
為了適應(yīng)各種屏幕尺寸和平板等設(shè)備的開(kāi)發(fā)再芋,F(xiàn)ragment被引入到API11級(jí)中剩胁,F(xiàn)ragment有著自己的生命周期,可以把Fragment當(dāng)做是Activity的一部分,在Activity中达吞,可以動(dòng)態(tài)的添加,移除和替換Activity荒典。
fragment有兩個(gè)支持向后兼容的Android庫(kù):
*android.support.v4.app.Fragment(該類(lèi)可以用在任何API4級(jí)及更高的版本上)
*android.support.v4.app.FragmentActivity(支持在較老的版本上(Honeycomb前)activit也可多fragment進(jìn)行管理
Fragment生命周期
Fragment的生命周期類(lèi)似Activity的生命周期酪劫,它與Activity生命周期的區(qū)別在于:Fragment生命周期是有托管activity而不是操作系統(tǒng)調(diào)用的,操作系統(tǒng)無(wú)從知曉activity用來(lái)管理視圖的fragment寺董,fragment的使用時(shí)activity自己內(nèi)部的事情覆糟。生命周期:
可以看到Fragment比Activity多了幾個(gè)額外的生命周期回調(diào)方法:
onAttach(Activity)
當(dāng)Fragment與Activity發(fā)生關(guān)聯(lián)時(shí)調(diào)用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
創(chuàng)建該Fragment的視圖
onActivityCreated(Bundle)
當(dāng)Activity的onCreate方法返回時(shí)調(diào)用
onDestoryView()
與onCreateView想對(duì)應(yīng)遮咖,當(dāng)該Fragment的視圖被移除時(shí)調(diào)用
onDetach()
與onAttach相對(duì)應(yīng)滩字,當(dāng)Fragment與Activity關(guān)聯(lián)被取消時(shí)調(diào)用
注意:除了onCreateView,其他的所有方法如果你重寫(xiě)了,必須調(diào)用父類(lèi)對(duì)于該方法的實(shí)現(xiàn)
Fragment的使用
為托管UI fragment麦箍,activity必須做到:
- 在布局中為fragment安排位置漓藕;
- 管理fragment實(shí)例的生命周期;
而在activity中托管fragment内列,有如下兩種方式: - 添加fragment到布局中(靜態(tài))撵术;
- 在activity代碼中添加fragment。
第一種方式即使用布局fragment话瞧,這種方式雖然簡(jiǎn)單嫩与,但靈活性不夠,等同于將fragment及其視圖與activity視圖綁在了一起交排,且在activity的生命周期中划滋,無(wú)法切換視圖。
下面來(lái)看看第一種的用法:
- 繼承fragment埃篓,重寫(xiě)onCreateView實(shí)例化fragment的布局处坪;
- 在activity布局中聲明此布局(通過(guò)android:name屬性顯示指明要添加的碎片類(lèi)名)
fragment布局:
<?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">
<TextView
android:id="@+id/tv_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="第一個(gè)fragment"
android:background="#00FF00"/>
</LinearLayout>
FirstFragment
package com.example.j.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by j on 2016/8/14.
*/
public class FirstFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.content_fragment, container, false);
}
}
activity_main_layout:
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.example.j.fragment.MainActivity">
<fragment
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.j.fragment.FirstFragment" />
</RelativeLayout>
MainActivity:
package com.example.j.fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
效果如圖:
二 動(dòng)態(tài)的使用fragment
動(dòng)態(tài)的使用fragment主要有fragment的增加,替換架专,移除等操作同窘,這種使用方法靈活性較高,也相對(duì)復(fù)雜一點(diǎn)一點(diǎn)
更改activity_main_layout:
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.example.j.fragment.MainActivity">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
同樣更改MainActivity:
package com.example.j.fragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.container);
if (fragment == null) {
fragment = new FirstFragment();
fm.beginTransaction().add(R.id.container, fragment).commit();
}
}
}
運(yùn)行后部脚,發(fā)現(xiàn)這個(gè)效果更上圖是一樣的想邦,這里就不貼了。
簡(jiǎn)單的總結(jié)一下添加fragment的步驟委刘,其實(shí)與創(chuàng)建activity是差不多的:
- 通過(guò)定義布局文件中的組件丧没,組裝界面;
- 創(chuàng)建fragment類(lèi)并設(shè)置其視圖為定義的布局锡移;
- 通過(guò)代碼的方式呕童,鏈接布局文件中生成的組件;
可以看到淆珊,在activity中管理fragment是由FragmentManager完成的夺饲,直接在activity中調(diào)用getSupportFragmentManager()就可得到,F(xiàn)ragmenManager類(lèi)具體管理的是:
- fragment隊(duì)列施符;
- fragment事務(wù)的回退棧钞支;
add(...)方法是整個(gè)事務(wù)的核心部分,并含有兩個(gè)參數(shù)操刀,即容器視圖資源id,和新創(chuàng)建的fragment烁挟,容器視圖資源id是定義在主布局中的Framelayout組件的資源id,主要有兩個(gè)作用:
- 告知FragmentManager骨坑,fragment該出現(xiàn)在視圖的什么位置撼嗓;
- 是FragmentManager隊(duì)列中fragment的唯一標(biāo)識(shí)符
以下為復(fù)制內(nèi)容:
a柬采、獲取FragmentManage的方式:
getFragmentManager() // v4中,getSupportFragmentManager
b且警、主要的操作都是FragmentTransaction的方法
FragmentTransaction transaction = fm.benginTransatcion();//開(kāi)啟一個(gè)事務(wù)
**transaction.add() **
往Activity中添加一個(gè)Fragment
**transaction.remove() **
從Activity中移除一個(gè)Fragment粉捻,如果被移除的Fragment沒(méi)有添加到回退棧(回退棧后面會(huì)詳細(xì)說(shuō)),這個(gè)Fragment實(shí)例將會(huì)被銷(xiāo)毀斑芜。
transaction.replace()
使用另一個(gè)Fragment替換當(dāng)前的肩刃,實(shí)際上就是remove()然后add()的合體~
transaction.hide()
隱藏當(dāng)前的Fragment,僅僅是設(shè)為不可見(jiàn)杏头,并不會(huì)銷(xiāo)毀
transaction.show()
顯示之前隱藏的Fragment
detach()
會(huì)將view從UI中移除,和remove()不同,此時(shí)fragment的狀態(tài)依然由FragmentManager維護(hù)盈包。
attach()
重建view視圖,附加到UI上并顯示醇王。
transatcion.commit()//提交一個(gè)事務(wù)
注意:常用Fragment的哥們呢燥,可能會(huì)經(jīng)常遇到這樣Activity狀態(tài)不一致:State loss這樣的錯(cuò)誤。主要是因?yàn)椋篶ommit方法一定要在Activity.onSaveInstance()之前調(diào)用寓娩。
上述叛氨,基本是操作Fragment的所有的方式了,在一個(gè)事務(wù)開(kāi)啟到提交可以進(jìn)行多個(gè)的添加棘伴、移除寞埠、替換等操作。
值得注意的是:如果你喜歡使用Fragment焊夸,一定要清楚這些方法畸裳,哪個(gè)會(huì)銷(xiāo)毀視圖,哪個(gè)會(huì)銷(xiāo)毀實(shí)例淳地,哪個(gè)僅僅只是隱藏,這樣才能更好的使用它們帅容。
a颇象、比如:我在FragmentA中的EditText填了一些數(shù)據(jù),當(dāng)切換到FragmentB時(shí)并徘,如果希望會(huì)到A還能看到數(shù)據(jù)遣钳,則適合你的就是hide和show;也就是說(shuō)麦乞,希望保留用戶操作的面板蕴茴,你可以使用hide和show,當(dāng)然了不要使勁在那new實(shí)例姐直,進(jìn)行下非null判斷倦淀。
b、再比如:我不希望保留用戶操作声畏,你可以使用remove()撞叽,然后add()姻成;或者使用replace()這個(gè)和remove,add是相同的效果。
c愿棋、remove和detach有一點(diǎn)細(xì)微的區(qū)別科展,在不考慮回退棧的情況下,remove會(huì)銷(xiāo)毀整個(gè)Fragment實(shí)例糠雨,而detach則只是銷(xiāo)毀其視圖結(jié)構(gòu)才睹,實(shí)例并不會(huì)被銷(xiāo)毀。那么二者怎么取舍使用呢甘邀?如果你的當(dāng)前Activity一直存在琅攘,那么在不希望保留用戶操作的時(shí)候,你可以優(yōu)先使用detach鹃答。
上述已經(jīng)介紹完成了Fragment常用的一些方法乎澄,相信看完,大家一定清楚了Fragment的產(chǎn)生理由测摔,以及如何使用Fragment置济,再根據(jù)API的講解,也能明白锋八,曾經(jīng)為何覺(jué)得Fragment會(huì)出現(xiàn)一些列亂七八槽的問(wèn)題浙于,終究是因?yàn)闆](méi)有弄清楚其生命周期。
內(nèi)容來(lái)源:http://blog.csdn.net/lmj623565791/article/details/37970961
《第一行代碼》
《Android編程權(quán)威指南》