原理
在其布局中为fragment的视图安排位置。
管理fragment实例的生命周期。
fragmnet生命周期
fragment的生命周期方法由托管activity而不是操作系统调用,fragment的使用是activity内部的事情。
activity托管UI fragment的方式
1. 在activity布局中添加fragment
- 特点:使用布局fragment在activity布局中添加fragment
- 缺点:将fragment及其视图与activity的视图绑定在一起,activity周期内无法替换fragment视图
2. 在activity代码中添加fragment(推荐)
- 特点:可以动态控制fragment,也可以移除fragment,用其他fragment代替当前fragment
简单例子
1. 在 layout 目录中 创建一个fragment(如果是在Android studio中创建会自动生成 xml和Java文件),命名为: fragment_crime.xml , 重写xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:orientation="vertical">
<CheckBox
android:id="@+id/crime_solved"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/crime_solved_label" />
</LinearLayout>
2. 自动生成的Java文件为 CrimeFragment.java,重写它
注意:
1. fragment的视图并没有在 Fragment.onCreate(Bundle) 方法中生成
创建和配置 fragment 视图是另一个 Fragment 生命周期方法完成的:onCreateView
2. fragment的视图是直接通过调用 LayoutInflater.inflate(...) 方法并传入布局的资源ID生成的
第一个参数:资源id
第二个参数: 视图的父视图(不用改)
第三个参数:告诉布局生成器是否将生成的视图添加给父视图
public class CrimeFragment extends Fragment {
private CheckBox mSolvedCheckBox;
// onCreate 生命周期 这里并不负责创建视图
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
// 这里负责创建视图并,还可以控制视图中的各种控件
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_crime, container, false);
/* 这里为这个多选框设定一个选中事件,选中时 弹出吐司提示:你点击了多选框 */
mSolvedCheckBox = (CheckBox)v.findViewById(R.id.crime_solved);
mSolvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Toast.makeText(getContext(),"你点击了多选框",Toast.LENGTH_SHORT).show();
}
});
return v;
}
}
3. 处理 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- 新增的代码如下,这里创建了一个容器 -->
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
4. 处理 MainActivity.java , 在 onCreate 生命周期函数中添加
// FragmentManager 类负责管理fragment并将它们的视图添加到 activity 的视图层级结构中
FragmentManager fm = getSupportFragmentManager();
// 创建一个新的fragment事务,执行一个fragment添加操作,然后提交该事务
// 也就是说 把 CrimeFragment对应的xml 填充进去 R.id.fragment_container 对应的 容器
fm.beginTransaction()
.add(R.id.fragment_container, new CrimeFragment())
.commit();
以此,fragment_crime.xml 中的代码将会代替 这个容器,包括 FragmentCrime.java 中定义的各种行为将会实现
5.
设备旋转或回收内存时,Android系统会销毁Activity,而后重建时,会调用onCreate(Bundle)方法,但是它的FragmentManager会将fragment队列保存下来这样,activity重建时,新的
FragmentManager会首先获取保存的队列,然后重建fragment队列,从而恢复到原来的状态,因此需要改进 4. 中的代码
// 获取一个fragment交给 FragmentManager 它管理 (第一次打开时的容器是空的,也就是 fragment == null)
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
// 假如容器为空
if (fragment == null) {
// “创建一个新的fragment事务,执行一个fragment添加操作,然后提交该事务
// 也就是说 把 CrimeFragment对应的xml 填充进去 R.id.fragment_container 对应的 容器,这样该容器就不为null了
fm.beginTransaction()
.add(R.id.fragment_container, new CrimeFragment())
.commit();
}
这样每次重建都会判断是否有存在的fragment队列,就不会反复创建了,直接从队列里取到。