一、简介
Fragment 是一种可以嵌入在活动当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间。
二、优点
解决了手机,平板等各种设备的适配问题;
解决了多个 Activity 之间切换性能问题,使用更灵活;
减少 Activity 的代码量,UI 解耦;
复用性好;
响应速度快,占用内存低。
三、生命周期
Fragment 必须是依存于 Activity 而存在的,因此 Activity 的生命周期会直接影响到 Fragment 的生命周期。(1)onAttach(Activity):当 Activity 与 Fragment 发生关联时调用
(2)onCreate:创建 Fragment
(3)onCreateView(LayoutInflater,ViewGroup,Bundle):创建 Fragment 的视图
(4)onActivityCreate(bundle):当 Activity 的 onCreate() 方法返回时调用
(5)onDestoryView():当 Fragment 被移除时调用
(6)onDetach():当 Fragment 与 Activity 取消关联时调用
四、使用
4.1 创建 Fragment
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background=”#ffff00″
android:orientation=”vertical” >
<TextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_gravity=”center_horizontal”
android:textSize=”20sp”
android:text=”This is another right fragment”/>
</LinearLayout>
public class Fragment1 extends Fragment{
private static String ARG_PARAM = “param_key”;
private String mParam;
private Activity mActivity;
public void onAttach(Context context) {
mActivity = (Activity) context;
mParam = getArguments().getString(ARG_PARAM); // 获取参数
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_1, container, false);
TextView view = root.findViewById(R.id.text);
view.setText(mParam);
return root;
}
public static Fragment1 newInstance(String str) {
Fragment1 frag = new Fragment1();
Bundle bundle = new Bundle();
bundle.putString(ARG_PARAM, str);
fragment.setArguments(bundle); // 设置参数
return fragment;
}
}
如果在创建 Fragment 时要传入参数,必须要通过 setArguments(Bundle bundle) 方式添加,而不建议通过为 Fragment 添加带参数的构造函数,因为通过 setArguments() 方式添加,在由于内存紧张导致 Fragment 被系统杀掉并恢复(re-instantiate)时能保留这些数据。使用 newInstance(参数)的好处是,只需关注参数,不需关注 key 值是什么。
4.2 加载 Fragment
静态加载,fragment 标签
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<!– 静态加载 Fragment –>
<fragment
android:id=”@+id/left_fragment”
android:name=”com.example.fragmenttest.LeftFragment”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”1″ />
</LinearLayout>
动态加载,FrameLayout 存放 fragment 的容器
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<FrameLayout
android:id=”@+id/right_layout”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”1″ >
<!– 可以在这个容器中动态加载 Fragment –>
<fragment
android:id=”@+id/right_fragment”
android:name=”com.example.fragmenttest.RightFragment”
android:layout_width=”match_parent”
android:layout_height=”match_parent” />
</FrameLayout>
</LinearLayout>
AnotherRightFragment fragment = new AnotherRightFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager. beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.commit();
1. 创建待添加的碎片实例;2. 获取到 FragmentManager,在活动中可以直接调用 getFragmentManager() 方法得到;3. 开启一个事务,通过调用 beginTransaction() 方法开启;4. 向容器内加入碎片,一般使用 replace() 方法实现,需要传入容器的 id 和待添加的碎片实例;5. 提交事务,调用 commit() 方法来完成。
4.3 transaction 常用方法:(1)transaction.add(FrameLayout 的 id,Fragment 对象,tag 名):往 Activity 中添加一个 Fragment。
transaction.add(R.id.container, Fragment1.newInstance(“hello world”), “f1”)
(2)transaction.addToBackStack(String):添加一个(当前的)Fragment 到回退栈。
transaction.add(R.id.container, f1, “f1”)
.addToBackStack(“”)
.commit();
回退栈是由 FragmentManager 管理的。默认情况下,Fragment 事务是不会加入回退栈的,如果想将 Fragment 事务加入回退栈,则可以加入 addToBackStack(“”)。如果没有加入回退栈,则用户点击返回按钮会直接将 Activity 出栈;如果加入了回退栈,则用户点击返回按钮会回滚 Fragment 事务。
(3)transaction.remove(Fragment 对象):从 Activity 中移除一个 Fragment,如果被移除的 Fragment 没有添加到回退栈,这个 Fragment 实例将会被销毁。如果被移除的 Fragment 被添加到回退栈,实例不会被销毁,但视图会被销毁(即,按 back 键会显示,但是视图会被重新创建,不会保存视图状态)。
Fragment fragment = fragmentManager.findFragmentById(R.id.details_fragment);
transaction.remove(fragment);
transaction.commit();
(4)transaction.replace(Fragment id,Fragment 对象):使用另一个 Fragment 替换当前的,实际上就是 remove() 然后 add() 的合体。
(5)transaction.hide():隐藏当前的 Fragment,仅仅是设为不可见,并不会销毁。
(6)transaction.show():显示之前隐藏的 Fragment。
(7)detach():将此 Fragment 从 Activity 中分离,会销毁其布局,但不会销毁该实例。
(8)attach():将从 Activity 中分离的 Fragment,重新关联到该 Activity,重新创建其视图层次。
五、通讯
Activity 调用 Fragment 的方法
RightFragment rightFragment = (RightFragment) getFragmentManager().findFragmentById(R.id.right_fragment);
Fragment 调用 Activity 的方法
// 在每个碎片中都可以通过调用 getActivity() 方法来得到和当前碎片相关联的活动实例
MainActivity activity = (MainActivity) getActivity();
// 这种方式复用性差,最好使用接口的方式。