Fragment
Fragment最初是為了適應(yīng)不同屏幕尺寸誕生的,它可以加載一個(gè)視圖,然后對(duì)視圖進(jìn)行管理操作,類似于Activity,而Fragment本身又可作為一個(gè)視圖模塊,托管給Activity來(lái)管理。 這樣就減輕了Activity的負(fù)擔(dān),大部分的功能可以在Fragment里實(shí)現(xiàn),Activity只負(fù)責(zé)加載管理就可以了。
Fragment生命周期
Fragment與Activity類似,生命周期也有相似之處,但是多了與View和托管對(duì)象Activity有關(guān)的方法:
創(chuàng)建:
1.onAttach() Fragment與Activity關(guān)聯(lián)時(shí)調(diào)用
2.onCreate() Fragment初始化創(chuàng)建
3.onCreateView() 建立并返回Fragment的View
4.onViewCreated()該方法官方?jīng)]有介紹,實(shí)際上會(huì)調(diào)用,View創(chuàng)建完成時(shí)調(diào)用
5.onActivityCreated() 當(dāng)托管該Fragment的Activity完成創(chuàng)建(onCreate)時(shí)調(diào)用創(chuàng)建完成開(kāi)始運(yùn)行
1.onStart()
2.onResume()
- 轉(zhuǎn)入后臺(tái)
1.onPause()
2.onStop()
以上方法與Activity是一樣的,Activity調(diào)用時(shí),F(xiàn)ragment也會(huì)跟著調(diào)用。
結(jié)束
1.onDestroyView()與onActivityCreated()對(duì)應(yīng),F(xiàn)ragment視圖被移除時(shí)調(diào)用
2.onDestroy()
3.onDetach()與onAttach對(duì)應(yīng),與Activity解除關(guān)聯(lián)時(shí)調(diào)用。狀態(tài)保存與恢復(fù)
與Activity一樣,非正常退出Fragment時(shí),也會(huì)觸發(fā) onSaveInstanceState(Bundle outState)方法,將數(shù)據(jù)保存在Bundle中,恢復(fù)的時(shí)候會(huì)調(diào)用onViewRestrored(Bundle savedInstanceState)方法。在Activity中調(diào)用的方法是onRestoreInstanceState()。
Fragment使用
Fragment是API 11 才引入的,使用的時(shí)候有android.app.fragment和v4支持包兩個(gè)選項(xiàng)。獲取FragmentManager的API也不同,v4包中使用getSupportedFragmentManager,直接繼承的使用getFragmentManager
靜態(tài)使用Fragment
靜態(tài)使用是指將Fragment當(dāng)做一個(gè)空間,定義在Layout文件中。
先定義一個(gè)Fragment引用的layout文件:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="Item Frament">
</TextView>
然后新建Fragment,加載視圖:
public class ItemFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.item,container,false);
return v;
}
}
到這里Fragment的部分完成了,可以把這個(gè)Fragment當(dāng)做控件在XMl中直接引用,下面是Activity的layout文件
<?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/frag_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.cris.miniweather.model.fragment.ItemFragment"/>
</LinearLayout>
在Activity里setContentView設(shè)置這個(gè)layout就可以了。注意fragment控件必須指定id,否則會(huì)崩潰
動(dòng)態(tài)使用Fragment
和靜態(tài)使用步驟類似,都需要先建立好Fragment和它對(duì)應(yīng)的layout文件,不同的是在Activity中引用時(shí),使用FragmentManager來(lái)管理Fragment。
先完成Fragment使用的layout(frag_list),這里用了Recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list_title"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
Recyclerview的對(duì)應(yīng)的layout文件(item.xml),一個(gè)TextView:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_content"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="Item Frament">
</TextView>
然后建立Fragment(TitleListFragment.java),這里實(shí)現(xiàn)的是一個(gè)最簡(jiǎn)單的recyclerview
public class TitleListFragment extends android.support.v4.app.Fragment{
private List<String> mItems;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mItems = new ArrayList<>();
for(int i = 0; i<50; i++ ){
String item = "Title No." + i;
mItems.add(item);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.list_title,container,false);
RecyclerView mRecyclerView = (RecyclerView) v.findViewById(R.id.frag_list);
RecyclerView.LayoutManager manager=new LinearLayoutManager(getActivity());
manager.setAutoMeasureEnabled(true);
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setAdapter(new RecycleAdapter());
return v;
}
private class RecycleHolder extends RecyclerView.ViewHolder{
private TextView mTextView;
public RecycleHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView;
}
}
private class RecycleAdapter extends RecyclerView.Adapter<RecycleHolder>
{
@Override
public RecycleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View TitleItemView = LayoutInflater.from(getActivity()).inflate(R.layout.item,parent,false);
return new RecycleHolder(TitleItemView);
}
@Override
public void onBindViewHolder(RecycleHolder holder, int position) {
holder.mTextView.setText(mItems.get(position));
}
@Override
public int getItemCount() {
return mItems.size();
}
}
}
到這里,F(xiàn)ragment的部分已經(jīng)完成,可以在Activity里加載它了,先設(shè)置Activity的layout文件,一個(gè)空的FrameLayout,作為Fragment的容器:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/frag_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
在Activity里加載Fragment:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_container);
FragmentManager fm= getSupportFragmentManager();
if(fm.findFragmentById(R.id.frag_container) ==null) {
fm.beginTransaction()
.add(R.id.frag_container, new TitleListFragment())
.commit();
}
}
注意:
1.在Activity里是用FragmentManager來(lái)管理Fragment的,findFragmentById里的參數(shù)是Fragment容器的id,返回的是它所管理的Fragment。
2.在add方法之前,需要加一個(gè)判斷,如果為null才會(huì)去添加Fragment。因?yàn)锳ctivity非正常退出,并且被回收的時(shí)候,F(xiàn)ragmentManager 會(huì)將它所管理的Fragment隊(duì)列保存下次,Activity重新建立的時(shí)候,F(xiàn)ragmentManager 會(huì)先回復(fù)它所保存的隊(duì)列,并重建Fragment。
Fragment常用API
與Fragment相關(guān)的API主要有以下兩大類
- FragmentManager
- beginTransaction() 獲取FragmentTransaction對(duì)象,用來(lái)操作Fragment
- findFragmentById(id) 獲取id對(duì)應(yīng)的父容器中的當(dāng)前Fragment
- findFragmentByTag(String tag) 獲取tag對(duì)應(yīng)的Fragment,tag在add時(shí)添加
- getFragment(Bundle bundle, String key) 與putFragment對(duì)應(yīng),將一個(gè)Fragment對(duì)象放在Bundle數(shù)據(jù)中
- isDestroyed() 托管該Fragment的Activity執(zhí)行onDestroy后,會(huì)返回true。
- void popBackStack() 將棧頂對(duì)象彈出。相當(dāng)于back鍵
- saveFragmentInstanceState(Fragment f) 存儲(chǔ)f的狀態(tài)。
- FragmentTransaction
- add(Fragment fragment, String tag); 調(diào)用第三個(gè)方法,containerViewId為0
- add(int containerViewId, Fragment fragment) 調(diào)用第三個(gè)方法,tag為null
- add(int containerViewId, Fragment fragment, String tag);添加fragment到container中
- addToBackStack(String name)添加Fragment到name返回棧中,默認(rèn)為null
- attach(Fragment fragment) 在使用detach方法與UI解除關(guān)聯(lián)之后重新關(guān)聯(lián)
- commit() 提交事物
- detach(Fragment fragment) 從UI中解除Fragment的綁定。
- remove(Fragment fragment) 移除一個(gè)已經(jīng)存在了的Fragment。
- hide(Fragment fragment) 隱藏一個(gè)存在的Fragment
- show(Fragment fragment) 顯示一個(gè)之前隱藏的Fragment。
- replace(int containerViewId, Fragment fragment, String tag);替換一個(gè)已經(jīng)存在了的Fragment(先remove,在add)