14 Fragment

一、使用Fragment

1、自定义SecondFragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.xianxiaotao.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SecondFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_second, container, false);
root.findViewById(R.id.btnBackFirstFragment).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().getSupportFragmentManager().popBackStack(); // 返回
}
});
return root;
}
}

2、自定义FirstFragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.xianxiaotao.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FirstFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_first, container, false);
root.findViewById(R.id.btnStartSecondFragment).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { // SecondFragment替换当前的FirstFragment
getActivity().getSupportFragmentManager().beginTransaction()
.addToBackStack(null) /* 返回键返回上一个Fragment */
.replace(R.id.container, new SecondFragment())
.commit();
}
});
return root;
}
}

3、MainActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.xianxiaotao.fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new FirstFragment())
.commit();
}
}
}

4、布局文件activity_main.xml、fragment_first.xml 和 fragment_second.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<?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:orientation="vertical">
<TextView
android:text="This is first fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:text="Start Second Fragment"
android:textAllCaps="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnStartSecondFragment"/>
</LinearLayout>
<?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:orientation="vertical">
<TextView
android:text="This is second fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:text="Go Back"
android:textAllCaps="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnBackFirstFragment"/>
</LinearLayout>

5、静态使用Fragment

上述为动态的使用Fragment,静态的使用方式是在布局文件里指定使用哪个Fragment:

1
2
3
4
5
<fragment
android:id="@+id/fragment_first"
android:name="com.xianxiaotao.FirstFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

二、Fragment的生命周期

简述

Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。官网这张图很好的说明了两者生命周期的关系:
Fragment的生命周期
可以看到Fragment比Activity多了几个额外的生命周期回调方法:
onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用
注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现

测试

在上述Demo中每个Fragment里重写所有的生命周期方法以及MainActivity,并输出日志信息。如下:

1
2
3
4
5
@Override
public void onAttach(Context context) {
super.onAttach(context);
System.out.println("FirstFragment onAttach");
}

1、启动程序,在MainActivity的onCreate方法中引用了FirstFragment。日志如下:

1
2
3
4
5
6
7
8
9
MainActivity onCreate
FirstFragment onAttach
FirstFragment onCreate
FirstFragment onCreateView
FirstFragment onActivityCreated
FirstFragment onStart
MainActivity onStart
MainActivity onResume
FirstFragment onResume

2、Start Second Fragment,使用SecondFragment替换FirstFragment。日志:

1
2
3
4
5
6
7
8
9
SecondFragment onAttach
SecondFragment onCreate
FirstFragment onPause
FirstFragment onStop
FirstFragment onDestroyView
SecondFragment onCreateView
SecondFragment onActivityCreated
SecondFragment onStart
SecondFragment onResume

3、Go Back,由SecondFragment返回到FirstFragment。日志:

1
2
3
4
5
6
7
8
9
SecondFragment onPause
SecondFragment onStop
SecondFragment onDestroyView
SecondFragment onDestroy
SecondFragment onDetach
FirstFragment onCreateView
FirstFragment onActivityCreated
FirstFragment onStart
FirstFragment onResume

4、返回,即退出应用程序。日志:

1
2
3
4
5
6
7
8
FirstFragment onPause
MainActivity onPause
FirstFragment onStop
MainActivity onStop
FirstFragment onDestroyView
FirstFragment onDestroy
FirstFragment onDetach
MainActivity onDestroy