fragment总是嵌入一个activity 而且fragment的生命周期总是被它的host activity的生命周期直接影响。
比如:当activity暂停的时候,它所有的fragments都暂停;当activity摧毁的时候,所有的fragments都被摧毁。当activity在运行的时候(它在resumed 生命周期状态),你可以独立操作每一个fragment,比如增加、移除。当你执行一个fragment transaction时,你可以将它加入到activity管理的back stack。activity的back stack记录了发生的fragment transaction。back stack允许用户通过Back 键后撤一次fragment transaction
如果你想迁移一个已有的APP使用fragment,只要把activity的回调移植到你的fragment就可以了。
onCreate()
初始化fragment必要的部件
onCreateView()
fragment第一次绘制UI,你必须返回frame的layout的root view
onPause()
用户离开fragment,你必须提交那些在当前用户会话背后必须一致的change
Fragment的一些子类
(1)DialogFragment
展示一个浮动的对话框
(2)ListFragment
展示被adapter管理 的items list(比如:SimpleCursorAdapter)
(3)PreferanceFragment
对创建一个setting activity很有效
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saveInstance)
inflate()
参数:(1)layout的resource ID
(2)inflated layout的parent的ViewGroup
(3)是否inflated layout被附着到ViewGroup
如何添加fragment到activity的layout
(1)在layout 文件里面声明
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:name="com.example.news.ArticleListFragment"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="com.example.news.ArticleReaderFragment"
android:id="@+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
android:name 表示Fragment类
(2)在程序里面添加fragment到一个已知的ViewGroup
使用FragmentTransaction的API实现 fragment transactions(比如 add, remove, replace)
<span style="font-size:24px;">FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();</span>
然后使用add()加入一个fragment<span style="font-size:24px;">ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();</span>
如果fragment 没有UI
通过add(Fragment, String)(提供一个唯一的string 标签,而不是用view ID)
这种fragment不用实现onCreateView()
对于没有UI的fragment,只有string tag才能找到它;有UI的fragment,也可以有string tag
findFragmentByTag()
通过getFragmentManager()得到activity的FragmentManager
FragmentManager的功能:
(1)得到activity已有的fragment : finfFragmentById() / findFragmentByTag()
(2)将fragment从back stack 出栈: popBackStack()
(3)为back stack注册一个listener: addOnBackStackChangedListener()
Fragment Transactions:
add() , remove(), replace()
commit() 提交transaction 给activity
在commit()之前,如果调用addToBackStack()可以将这次transaction加入到back stack,这样允许后退键返回到之前的fragment state
<span style="font-size:24px;">// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();</span>
如果多个transaction之后才调用addToBackStack(),那么按下Back button会倒退这多个的transaction。
如果你在activity保存自己的状态(用户离开这个activity)之后使用commit()提交一个transaction,会出现异常,
这是因为activity恢复之后,commit之后的state会丢失。你可以使用commitAllowingStateLoss()
和 Activity通信
Fragment可以得到activity实例通过 getActivity(), 这样就可以找到这个activity的layout的其他view
View listView = getActivity().findViewById(R.id.list);
同样的,activity得到fragment
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
如何实现fragment和activity分享events,方法是fragment定义一个接口,然后它的host activity实现这个接口
当activity通过fragment内部的interface接收到事件时,它可以和layout的其他fragment分享这个event
举个例子:
fragment A用ListView显示不同的新闻栏目,fragment B用于选中某个栏目后具体的新闻信息
此时,在fragment A 中实现 OnArticleSelectedListener 接口
public static class FragmentA extends ListFragment {
...
// Container Activity must implement this interface
public interface OnArticleSelectedListener {
public void onArticleSelected(Uri articleUri);
}
...
}
然后host activity实现这个接口,重写onArticleSelected()函数,实现通知fragment B来自fragment A的event
为了保证host activity实现这个接口,可以在fragment A的onAttach()函数验证
这里如果强制类型转换成功,说明activity实现了该接口
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnArticleSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
}
}
...
}
如果没有实现该接口,会出现类型转换异常 ClassCastException
比如Fragment A继承自ListFragment ,那么每次用户点击一个items, 系统调用onListItemClick(), 在里面用onArticleSelected()来和activity分享这个event
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Append the clicked item's row ID with the content provider Uri
Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
// Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);
}
...
}
传递给onListItemClick()的参数 id是点击的items的row ID