Fragment的使用
因?yàn)锳ndroid-support-v4包里面的fragment比系統(tǒng)的功能更加的強(qiáng)大荒叼,所以我們所有的討論都圍繞android.support.v4.app.Fragment進(jìn)行荤崇。首先來學(xué)習(xí)一下Fragment的使用,Fragment必須依附于Activity,不能夠單獨(dú)存在罚攀。
1党觅、靜態(tài)添加Fragment
靜態(tài)添加Fragment,在布局文件中可以像添加普通控件一樣添加fragment斋泄,然后通過android:name
設(shè)置fragment的實(shí)現(xiàn)類杯瞻,在實(shí)現(xiàn)類中通過onCreateView方法中設(shè)置fragment的布局。
注意:必須要設(shè)置android:id
屬性是己,否則程序會出錯又兵。
StudyFragment,SecondFragment的布局如下
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Fragment Second"
android:gravity="center"
android:textSize="20sp"
android:background="#000000"
android:textColor="#ffffff"/>
</LinearLayout>
StudyFragment和SecondFragment加載布局的代碼
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_second,container,false);
}
MainActivity的布局如下
<?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">
<fragment
android:id="@+id/fragment_study1"
android:name="com.example.study.StudyFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<fragment
android:id="@+id/fragment_study2"
android:name="com.example.study.StudyFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<fragment
android:id="@+id/fragment_second"
android:name="com.example.study.SecondFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
需要注意的是卒废,使用v4包下的fragmet沛厨,Activity需要繼承v4包下的FragmentActivity,通常我們在AndroidStudio創(chuàng)建一個新的項(xiàng)目摔认,Activity都會默認(rèn)繼承v7包的AppCompatActivity逆皮,而AppCompatActivity繼承自FragmentActivity。如下
public class AppCompatActivity extends FragmentActivity implements AppCompatCallback,
TaskStackBuilder.SupportParentable, ActionBarDrawerToggle.DelegateProvider {
...
}
所以直接在我們的Activity中的onCreate調(diào)用setContentView参袱,就可以靜態(tài)加載Fragment
關(guān)于靜態(tài)加載Fragment還有一點(diǎn)需要補(bǔ)充的就是电谣,通常我們加載完之后,還是要獲得Fragment對象進(jìn)行操作的抹蚀,這個時候可通過FragmentManager下的findFragmentById()方法或者findFragmentByTag()方法獲取Fragment對象剿牺。
2、動態(tài)加載Fragment
就像我們可以動態(tài)地添加View到視圖中环壤,我們也可以動態(tài)地添加fragment到Activity晒来。下面就來學(xué)習(xí)一下動態(tài)添加Fragment。
雖然不想誤導(dǎo)大家郑现,但還是要給大家強(qiáng)調(diào)一下湃崩,當(dāng)我們動態(tài)添加Fragment到Activity的時候,就要使用到FragmentManager接箫,我們可以通過getFragmentManager()方法獲取的Fragment用于管理android.app.Fragment的實(shí)例攒读,對于android.support.v4.app.Fragment,我們使用getSupportFragmentManager()方法。
動態(tài)加載Fragment大致有四個步驟:
1辛友、使用getSupportFragmentManager()或者getFragmentManager()獲取一個FragmentManager對象薄扁,大多數(shù)情況下我們調(diào)用的是getSupportFragmentManager()
2、開啟一個事務(wù)废累,通過調(diào)用FragmentManager的beginTransaction()方法邓梅,返回一個FragmentTransaction對象
3、往事務(wù)中添加一系列的Fragment操作九默,一般使用add或者replace方法震放,添加Fragment到當(dāng)前Activity
4、提交事務(wù)驼修,調(diào)用FragmentTransaction的commit方法
下面的例子殿遂,我們通過代碼來動態(tài)添加Fragment到Activity中。我先直接上MainActivity的布局和代碼
layout_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.study.MainActivity">
<TextView
android:id="@+id/btn_addStudyFragment"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#000000"
android:gravity="center"
android:textColor="#ffffff"
android:text="addStudyFragment" />
<TextView
android:id="@+id/btn_addSecondFragment"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:background="#000000"
android:textColor="#ffffff"
android:text="addStudyFragment" />
<TextView
android:id="@+id/btn_check"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:background="#000000"
android:textColor="#ffffff"
android:text="check" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</ScrollView>
</LinearLayout>
MainActivity
public class MainActivity extends AppCompatActivity {
FragmentManager fragmentManager;
StudyFragment studyFragment;
SecondFragment secondFragment;
private TextView btn_addStudy;
private TextView btn_addSecond;
TextView btn_check;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
btn_addSecond = (TextView) findViewById(R.id.btn_addSecondFragment);
btn_addStudy = (TextView) findViewById(R.id.btn_addStudyFragment);
btn_check = (TextView)findViewById(R.id.btn_check);
btn_check.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//獲取添加到FragmentManager中的Fragment列表里面的Fragment
Fragment fragment1 = fragmentManager.getFragments().get(0);
Fragment fragment2 = fragmentManager.getFragments().get(2);
Log.e("true or false",(fragment1 instanceof StudyFragment) +"");
Log.e("true or false",(fragment2 instanceof StudyFragment) +"");
Log.e("true or false",(fragment1 == fragment2) +"");
}
});
btn_addStudy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addStudyFragment();
}
});
btn_addSecond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addSecondFragment();
}
});
}
//添加StudyFragment
private void addStudyFragment(){
studyFragment = new StudyFragment();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.fragment_container,studyFragment);
transaction.commit();
}
//添加SecondFragment
private void addSecondFragment(){
secondFragment = new SecondFragment();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.fragment_container,secondFragment);
transaction.commit();
}
}
運(yùn)行程序乙各,直接來一波操作墨礁。
當(dāng)我們反復(fù)添加Fragment進(jìn)FragmentManager的時候,那么我們要怎么對它進(jìn)行管理呢耳峦?同一個Fragment只能添加一次恩静,要是我們想要把一個Fragment添加多次,那么就要實(shí)例化多個Fragment對象才行。
注意:如果我們要對Fragment進(jìn)行操作的話驶乾,最好通過FragmentManager對Fragment進(jìn)行統(tǒng)一管理邑飒。
Fragment怎么與Activity交互
把Fragment加載到Activity后,我們知道Fragment必須依附于Activity级乐,那么Activity和Fragment交互有多少種方式呢疙咸?先從最簡單的說
1、如果Activity持有Fragment的實(shí)例风科,那么我們可以通過該Fragment直接調(diào)用Fragment里面的public方法撒轮,但是也是有坑的,就像我在上面說的贼穆,當(dāng)我們反復(fù)添加一個Fragment實(shí)例的話题山,最好還是通過FragmentManager來獲取對應(yīng)的實(shí)例,這樣減少出錯的幾率故痊。
2顶瞳、在Fragment中我們也可以通過getActivity()方法來得到當(dāng)前綁定的Activity實(shí)例,把該實(shí)例強(qiáng)轉(zhuǎn)成對應(yīng)的實(shí)例即可調(diào)用指定Activity的public方法崖蜜。
我們在開發(fā)中都會遇到的一個問題是浊仆,使用Fragment的一個好處就是我們可以重復(fù)使用,但是如果我們在ActivityA中使用了Fragment豫领,在ActivityB中也使用了Fragment抡柿,那我們調(diào)用getActivity()的時候就需要使用instanceof來判斷是哪一個類,這樣的話代碼的耦合度就很高了等恐。所以我們也可以斟酌著使用類似于回調(diào)洲劣,handler,廣播這樣的方式來進(jìn)行通信课蔬。
if(getActivity() instanceof xxxAactivity){
//do something
}
其實(shí)說到Fragment和Activity囱稽,Fragment和Fragment之間的通信,其實(shí)也無外乎是對象之間的訪問而已二跋,畢竟java是面向?qū)ο蟮恼骄m然activity和fragment有各自的生命周期,但是歸根到底也是對象而已扎即。只是當(dāng)我們熟悉Fragment和Activity的生命周期以后吞获,不至于寫出太生硬的代碼。
下面介紹一下接口回調(diào)方式具體怎么使用
(1)谚鄙、在Fragment中定義接口
private OnGetListener onGetListener;
public interface OnGetListener{
void onGet();
}
(2)各拷、在Fragment中對接口進(jìn)行設(shè)置
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnGetListener){
onGetListener = (OnGetListener) context;
}
}
(3)、在MainAactivity中實(shí)現(xiàn)對回調(diào)接口的實(shí)現(xiàn)
public class MainActivity extends AppCompatActivity implements SecondFragment.OnGetListener{
...
@Override
public void onGet() {
}
}
(4)闷营、在fragment中調(diào)用回調(diào)函數(shù)
private void doSomething(){
if (onGetListener != null){
onGetListener.onGet();
}
}
下一篇具體研究一下Fragment和Activity各自的生命周期