1. 基本介绍
2. 生命周期
onAttach()
Fragment和Activity建立关联的时候调用,被附加到Activity中去。
onCreate()
创建Fragment时调用。可以初始化想要在fragment中保持的那些必要组件,当fragment处于暂停或者停止状态之后可重新启用它们。
onCreateView()
在Fragment首次绘制其用户界面时调用。 为fragment绘制用户界面,这个函数必须返回所绘的fragment的根View,如果Fragment未提供用户界面,可以返回 null。所以在此方法中不要进行耗时操作。
onViewCreated()
在onCreateView()调用后调用,用户重写此方法进行fragment初始化UI和逻辑。
onActivityCreated()
当Activity中的onCreate方法执行完后调用。当需要用到context或者activity初始化完成的属性时,在此方法中处理,如动态的new一个非静态View,注册广播等也最好在此方法调用。
onPause()
系统将此方法作为用户离开Fragment的第一个信号(但并不总是意味着此Fragment会被销毁)进行调用。 通常可以在此方法内确认在当前用户会话结束后仍然有效的任何更改(因为用户可能不会返回)。
onStop()
Fragment切换到后台不可见时调用。
onDestroyView()
Fragment中的布局被移除时调用。
onDestroy()
Fragment被销毁时调用。
onDetach()
Fragment和Activity解除关联的时候调用。
注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现。
3. fragment 和 activity生命周期对照
主要是在创建和销毁阶段存在差异,添加了依附关系的建立、取消,以及视图的创建和销毁过程。
4. 基本使用
1. 静态使用
1.继承Fragment,简单展示文本内容
public class Test1Fragment extends Fragment{
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_test1, container, false);
}
}
2.Fragment布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是 fragment1"
android:textColor="#ff0000"
android:textSize="30sp" />
</LinearLayout>
3.Activity布局文件,代码没有任何操作
<?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"
tools:context="com.hftsoft.fragmentdemo.MainActivity">
<!--静态Fragment-->
<fragment
android:name="com.hftsoft.fragmentdemo.Test1Fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<fragment
android:name="com.hftsoft.fragmentdemo.Test2Fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</RelativeLayout>
4.效果展示
2. 动态使用
1.activity布局文件
<RelativeLayout 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"
tools:context="com.hftsoft.fragmentdemo.MainActivity">
<!--动态Fragment容器-->
<FrameLayout
android:id="@+id/frame_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:id="@+id/btn_1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null"
android:text="fragment1"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null"
android:text="fragment2"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null"
android:text="fragment3" />
<Button
android:id="@+id/btn_4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null"
android:text="fragment4" />
</LinearLayout>
</RelativeLayout>
2.activity进行动态设置fragment
public class MainActivity extends AppCompatActivity {
private TestD1Fragment mD1Fragment;
private TestD2Fragment mD2Fragment;
private TestD3Fragment mD3Fragment;
private TestD4Fragment mD4Fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setFirst();
}
/**
* 设置第一次进入默认展示Fragment
*/
private void setFirst() {
// 获取Fragment管理类
FragmentManager fm = getFragmentManager();
// 管理类开始一个事务
FragmentTransaction transaction = fm.beginTransaction();
// 创建Fragment实例
mD1Fragment = new TestD1Fragment();
// 使用Fragment 替换掉标志控件
transaction.replace(R.id.frame_content, mD1Fragment);
// 提交事务
transaction.commit();
}
@OnClick({R.id.btn_1, R.id.btn_2, R.id.btn_3, R.id.btn_4})
public void onClick(View view) {
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
switch (view.getId()) {
case R.id.btn_1:
if (mD1Fragment == null){
mD1Fragment = new TestD1Fragment();
}
transaction.replace(R.id.frame_content, mD1Fragment);
break;
case R.id.btn_2:
if (mD2Fragment == null){
mD2Fragment = new TestD2Fragment();
}
transaction.replace(R.id.frame_content, mD2Fragment);
break;
case R.id.btn_3:
if (mD3Fragment == null){
mD3Fragment = new TestD3Fragment();
}
transaction.replace(R.id.frame_content, mD3Fragment);
break;
case R.id.btn_4:
if (mD4Fragment == null){
mD4Fragment = new TestD4Fragment();
}
transaction.replace(R.id.frame_content, mD4Fragment);
break;
}
transaction.commit();
}
3.效果很简单,点击下面的按钮切换展示对应的fragment。
动态设置步骤:
// 1.获取Fragment管理类
FragmentManager fm = getFragmentManager();
// 2.管理类开始一个事务
FragmentTransaction transaction = fm.beginTransaction();
// 3.创建Fragment实例
mD1Fragment = new TestD1Fragment();
// 4.使用Fragment 替换掉标志控件
transaction.replace(R.id.frame_content, mD1Fragment);
// 5.提交事务
transaction.commit();
5. 任务栈管理
fragment类似于activity,都有一个任务栈进行管理,fragment的任务栈被acitivity对象持有。
activity代码如下:
/**
* fragment 任务栈管理演示
*
* @author fengzhen
* @version 1.0, 2017/6/8 17:09
*/
public class StackManageActivity extends AppCompatActivity {
private TestD1Fragment mD1Fragment;
private TestD2Fragment mD2Fragment;
private TestD3Fragment mD3Fragment;
private TestD4Fragment mD4Fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setFirst();
}
/**
* 设置第一次进入默认展示Fragment
*/
private void setFirst() {
// 获取Fragment管理类
FragmentManager fm = getFragmentManager();
// 管理类开始一个事务
FragmentTransaction transaction = fm.beginTransaction();
// 创建Fragment实例
mD1Fragment = new TestD1Fragment();
// 使用Fragment 替换掉标志控件
transaction.replace(R.id.frame_content, mD1Fragment);
// 提交事务
transaction.commit();
}
@OnClick({R.id.btn_1, R.id.btn_2, R.id.btn_3, R.id.btn_4})
public void onClick(View view) {
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
switch (view.getId()) {
case R.id.btn_1:
if (mD1Fragment == null){
mD1Fragment = new TestD1Fragment();
}
transaction.replace(R.id.frame_content, mD1Fragment);
// 将移除的fragment添加到任务栈中
transaction.addToBackStack(null);
break;
case R.id.btn_2:
if (mD2Fragment == null){
mD2Fragment = new TestD2Fragment();
}
transaction.replace(R.id.frame_content, mD2Fragment);
transaction.addToBackStack(null);
break;
case R.id.btn_3:
if (mD3Fragment == null){
mD3Fragment = new TestD3Fragment();
}
transaction.replace(R.id.frame_content, mD3Fragment);
transaction.addToBackStack(null);
break;
case R.id.btn_4:
if (mD4Fragment == null){
mD4Fragment = new TestD4Fragment();
}
transaction.replace(R.id.frame_content, mD4Fragment);
transaction.addToBackStack(null);
break;
}
transaction.commit();
}
}
transaction.addToBackStack(null);
将remove()的fragment添加到任务栈中,如果不添加被替换掉的fragment就可能被后台销毁。
暂时没有弄明白name的用处。。。
fm.popBackStack()
回退任务栈。也可通过物理返回键实现。
注意:这里的回退是回退一个事务,而不是一个fragment。
fm.findFragmentByTag(String tag)
根据transaction.add()(replace() 相当于 先remove(),再add()) 方法传入的tag值查找fragment。
注意:
replace()不会销毁fragment实例,但是会销毁视图,即会调用onDestroyView()方法,所以不能直接保存上一个fragment控件状态。
可以使用hide() + add()配合使用,不销毁fragment实例。
或者onSaveInstanceState()方法进行现场保护,再onViewCreated()恢复现场。
hide()和show()方式进行Fragment管理
此种情况不会调用任务生命周期方法,只会调用onHiddenChanged()方法。如果通过此种方式进行Fragment的管理,fragment刷新UI、刷新数据等操作必须都放在onHiddenChanged()进行。
@Override
public void onHiddenChanged(boolean hidden) {
if (hidden) {
// 隐藏后的操作
}else{
// 显示后的操作
}
super.onHiddenChanged(hidden);
}
6. Fragment事务处理
每一次对fragment的replace()、remove()、add()等一系列操作都需要commit()给activity进行处理,activity并不是立刻调用,而是在主线程准备好后调用。
7. 与Activity交互
1. 互相获取
fragment中获取activity索引:
getActivity()
Activity activity = getActivity();
activity获取fragment索引:
1.直接拿fragment来使用
2.getFragmentManager().findFragmentByTag()
transaction.replace(R.id.frame_content, mD1Fragment,"fragment tag");
// 后面的tag是replace、add传入的
TestD1Fragment fragment1 = (TestD1Fragment)getFragmentManager().findFragmentByTag("fragment tag");
// 静态fragment使用 findFragmentById(布局id值)
2. activity事件回调方法实现通讯
需要fragment与activity共享事件,fragment将方法抛出给activity具体实现,实现fragment不与activity耦合。
fragment中代码实现:
/**
* 外抛接口给activity调用
*
* @author fengzhen
* @version 1.0, 2017/6/9 16:52
*/
public interface HandleActivityListener {
void doSomething();
}
// 持有监听
private HandleActivityListener mListener;
/**
* 设置监听
*/
public void setHandleActivityListener(HandleActivityListener listener) {
mListener = listener;
}
/**
* 监听
*/
private void todoSomething() {
if (mListener != null) {
mListener.doSomething();
}
}
activity代码实现:
mD1Fragment.setHandleActivityListener(new TestD1Fragment.HandleActivityListener() {
@Override
public void doSomething() {
// do something
}
});
8. 特殊的Fragment
DialogFragment、ListFragment、PreferenceFragment