【笔记】Android片段Fragment

前言

Android片段Fragment学习笔记
Fragment可以比作一个子Activity
Fragment必须委托在Activity中才能运行,Fragment有自己的生命周期,同时也被其宿主Activity生命周期所左右

创建Fragment

  • 创建两个Fragment用于测试多个Fragment

  • 为了区分,设置第一个Fragment背景色为红色

/app/src/main/res/layout/fragment1.xml
1
2
3
4
5
6
7
8
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000">

...

</LinearLayout>

R.layout.fragment:绑定刚刚创建的xml文件

/app/src/main/java/.../Fragment1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Fragment1 extends androidx.fragment.app.Fragment {

private View root;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (root == null) {
root = inflater.inflate(R.layout.fragment1, container, false);
}

...

return root;
}
}
  • 第二个Fragment背景色为绿色
/app/src/main/res/layout/fragment2.xml
1
2
3
4
5
6
7
8
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FF00">

...

</LinearLayout>

R.layout.fragment:绑定刚刚创建的xml文件

/app/src/main/java/.../Fragment2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Fragment2 extends androidx.fragment.app.Fragment {

private View root;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (root == null) {
root = inflater.inflate(R.layout.fragment2, container, false);
}

...

return root;
}
}

静态添加Fragment

添加一个Fragment到主布局

android:id="@+id/fm":Fragment一定要添加id
android:name="com.Fragment":Fragment的name要填写java类的全局限定名

/app/src/main/res/layout/activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment
android:id="@+id/fm"
android:name="com.Fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</LinearLayout>

添加多个Fragment到主布局

/app/src/main/res/layout/activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment
android:id="@+id/fm1"
android:name="com.Fragment1"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<fragment
android:id="@+id/fm2"
android:name="com.Fragment2"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</LinearLayout>

动态添加Fragment

在主界面添加FrameLayout

  • 在主界面添加按钮和FrameLayout,实现点击不同按钮时,将不同Fragment渲染在FrameLayout上
/app/src/main/res/layout/activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<FrameLayout
android:id="@+id/fl"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</LinearLayout>

设置按钮的点击事件

  • 点击时间既可以通过匿名内部类创建,也可以通过实现View.OnClickListener接口并重写onClick(View view)方法实现。这里采用第二种方式进行测试

fragmentTransaction.addToBackStack(null);:通过返回栈栈对Fragment管理(可选)。实现每一次添加Fragment都放到返回栈栈顶,每次按返回键,都从返回栈栈顶移除一个Fragment

/app/src/main/java/.../MainActivity.java
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
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Button btn1 = findViewById(R.id.btn1);
btn1.setOnClickListener(this);
Button btn2 = findViewById(R.id.btn2);
btn2.setOnClickListener(this);
}

@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn1:
replaceFragment(new Fragment1());
break;
case R.id.btn2:
replaceFragment(new Fragment2());
break;
}
}

// 动态切换Fragment
private void replaceFragment(Fragment fragment) {
// 获取Fragment管理器
FragmentManager fragmentManager = getSupportFragmentManager();
// 通过管理器,获取Transaction对象,通过Transaction对象管理Fragment
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// 创建切换Fragment的事件
fragmentTransaction.replace(R.id.fl, fragment);
// 添加返回栈
fragmentTransaction.addToBackStack(null);
// 提交事件
fragmentTransaction.commit();
}
}

Activity与Fragment通信

通过Bundle携带参数(原生)

  • Activity向Fragment传递参数

在MainActivity传递Activity的参数

/app/src/main/java/.../MainActivity.java
1
2
3
4
5
6
7
8
// 创建bundle对象
Bundle bundle = new Bundle();
// 设置bundle对象携带的参数
bundle.putString("message", "string");
// 创建Fragment对象
Fragment1 fragment1 = new Fragment1();
// 设置Fragment对象携带的参数
fragment1.setArguments(bundle);

在Fragment获取参数

/app/src/main/java/.../Fragment.java
1
2
Bundle bundle = this.getArguments();
String message = bundle.getString("message");

通过接口携带参数

  • Activity与Fragment互相传递参数

创建一个接口

/app/src/main/java/.../IFragmentCallback.java
1
2
3
4
public interface IFragmentCallback {
void sendMessageToActivity(String message);
String getMessageFromActivity();
}

在Fragment类中定义接口为属性

  • 创建Fragment类,将IFragmentCallback接口作为Fragment类的属性,并定义其set方法
/app/src/main/java/.../Fragment.java
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
public class Fragment extends androidx.fragment.app.Fragment {

private View root;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (root == null) {
root = inflater.inflate(R.layout.fragment1, container, false);
}

...

return root;
}

private IFragmentCallback fragmentCallback;
public void setFragmentCallback(IFragmentCallback fragmentCallback) {
this.fragmentCallback = fragmentCallback;
}
}

从Fragment传递参数到Activity

从Fragment传递参数

<msg>:传递的信息

/app/src/main/java/.../Fragment.java
1
fragmentCallback.sendMessageToActivity(<msg>);
在Activity接收
/app/src/main/java/.../MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Fragment fragment = new Fragment();
fragment.setFragmentCallback(new IFragmentCallback() {
@Override
public void sendMessageToActivity(String message) {

// 在这里接收
...

}

@Override
public String getMessageFromActivity() {
return null;
}
});

从Activity传递参数到Fragment

从Activity传递参数

<msg>:传递的信息

/app/src/main/java/.../MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Fragment fragment = new Fragment();
fragment.setFragmentCallback(new IFragmentCallback() {
@Override
public void sendMessageToActivity(String message) {

}

@Override
public String getMessageFromActivity() {

// 在这里发送
return <msg>;
}
});
在Fragment接收
/app/src/main/java/.../Fragment.java
1
fragmentCallback.getMessageFromActivity();

Fragment生命周期

  • onAttach()->onCreate->onCreateView()->onActivityCreate()->onStart()->onResume()->onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()

与Activity绑定/解绑:onAttach()/onDetach()
Fragment的创建/销毁:onCreate()/onDestroy()
对UI的创建:onCreateView()/onDestroyView()
Activity创建:onActivityCreate()

打开界面

  • onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()

按主屏幕键

  • onPause()->onStop()

重新打开界面

  • onStart()->onResume()

按后退键(退出应用)

  • onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()

完成

参考文献

哔哩哔哩——Android架构解析