Activity和Fragment的通信

在学习他们的通信之前,还是要先深入了解一下Fragment的创建、替换还有删除。

Fragment的基础知识

在动态创建完Fragment运行时发生了报错,错误的原因是我没有理解清楚fragment和FrameLayout的概念

他们的相同点都是用来放Fragment的,区别就是fragment标签只能设置固定的Fragment,而FrameLayout中可以通过FragmentManager更换Fragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<Button
android:id="@+id/replace"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="替换一个Fragment"/>
<Button
android:id="@+id/delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="删除一个Fragment"/>

//错误点就是这里 之前用的是fragment
<FrameLayout
android:id="@+id/fragment"
android:layout_width="300dp"
android:layout_marginTop="40dp"
android:layout_height="300dp" />
</LinearLayout>

Fragment的创建、替换还有删除

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
43
44
45
46
47
48
49
50
package com.example.study.communication;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;

import com.example.study.R;

public class MainActivity extends AppCompatActivity {

private Button replace;
private Button delete;
private Fragment f1;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_communication);

replace = (Button) findViewById(R.id.replace);
delete = (Button) findViewById(R.id.delete);

f1 = new FirstFragment();
//创建添加一个Fragment
getSupportFragmentManager().beginTransaction().add(R.id.fragment, f1).commit();

//替换一个Fragment
replace.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getSupportFragmentManager().
beginTransaction().replace(R.id.fragment, new SecondFragment())
//Fragment被替换后,点击返回键,可以返回到替换前的状态
.addToBackStack(null)
.commit();
}
});
//删除一个Fragment
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getSupportFragmentManager().beginTransaction().remove(f1).commit();
}
});
}
}

第一种通信方式 (fragment)

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class IndexActivity extends AppCompatActivity {

private CheckBox checkBox;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index);
checkBox = (CheckBox) findViewById(R.id.check_box);
//通过fragment设置固定的fragment,然后获取到所属fragment的控件
FragmentBottom fragment = (FragmentBottom) getSupportFragmentManager().findFragmentById(R.id.fragment_bottom);
TextView txtResult = (TextView) fragment.getView().findViewById(R.id.exhibition);
//Activity的变化改变Fragment某些内容的改变
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(checkBox.isChecked()){
if(fragment != null){
txtResult.setText("选中了");
}
} else {
if(fragment != null){
txtResult.setText("未选中");
}
}
}
});
}
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<CheckBox
android:id="@+id/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="isShow"/>

<fragment
android:id="@+id/fragment_bottom"
android:layout_width="match_parent"
android:layout_gravity="bottom"
android:name="com.example.study.communication.FragmentBottom"
android:layout_height="300dp" />
</LinearLayout>

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_bottom, container, false);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="40dp">


<TextView
android:id="@+id/exhibition"
android:layout_width="0dp"
android:layout_weight="1"
android:background="#353"
android:textColor="@color/white"
android:layout_height="match_parent" />

<Button
android:text="judge"
android:layout_width="0dp"
android:layout_weight="1"
android:background="#353"
android:layout_height="match_parent" />
</LinearLayout>

第二种通信方式(FrameLayout)

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
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<CheckBox
android:id="@+id/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="isShow"/>

<FrameLayout
android:id="@+id/fragment_bottom"
android:layout_width="match_parent"
android:layout_gravity="bottom"
android:layout_height="300dp" />
</LinearLayout>

public class IndexActivity extends AppCompatActivity {

private CheckBox checkBox;
private FragmentBottom fragment;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index);
checkBox = (CheckBox) findViewById(R.id.check_box);
//new了一个fragment对象
fragment = new FragmentBottom();
//将new出来的Fragment添加到Activity中
getSupportFragmentManager().beginTransaction().add(R.id.fragment_bottom, fragment).commit();

checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
TextView txtResult;
if(checkBox.isChecked()){
if(fragment != null){
//控件可以直接通过fragment.getView().findViewById()去拿
txtResult = (TextView) fragment.getView().findViewById(R.id.exhibition);
txtResult.setText("选中了");
}
} else {
if(fragment != null){
txtResult = (TextView) fragment.getView().findViewById(R.id.exhibition);
txtResult.setText("未选中");
}
}
}
});
}
}

第三种通信方式(这种方式不太好)

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
public class FragmentBottom extends Fragment {

private Button btnJudgement;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

View view = inflater.inflate(R.layout.fragment_bottom, container, false);
btnJudgement = (Button) view.findViewById(R.id.btn_judgement);
return view;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//fragment获取到Activity里的控件
final CheckBox checkBox = (CheckBox) getActivity().findViewById(R.id.check_box);
btnJudgement.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(checkBox != null){
if(checkBox.isChecked()){
Toast.makeText(getContext(), "选中了", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getContext(), "未选中", Toast.LENGTH_LONG).show();
}
}
}
});
}
}

第四种通信方式(最佳通信方式)

这个Demo所做得功能就是在获取到EditText输入的数据后,我们需要利用接口的方式将数据传递给其附着的Activity,然后该Activity或者所附着该Activity的另一个Fragment可以通过该接口获取到想要的数据。这样的话Fragment和Activity通信、Fragment与另一个Fragment通信,都应该依靠他们所附着的Activity来完成通信代码,而不是在Fragment直接获得这个引用来完成业务代码。

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment
android:id="@+id/fragment_new_item"
android:layout_width="match_parent"
android:name="com.example.study.communication.NewItemFragment"
android:layout_height="wrap_content" />

<fragment
android:id="@+id/fragment_to_do_list"
android:layout_width="match_parent"
android:layout_height="400dp"
android:name="com.example.study.communication.ToDoListFragment"
android:layout_marginTop="20dp"/>

</LinearLayout>

public class ExampleActivity extends AppCompatActivity implements NewItemFragment.OnNewItemAddListener{
private ArrayList<Object> data;
private ArrayAdapter<Object> adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);

//初始化数据
data = new ArrayList<>();

adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, data);
ToDoListFragment fragment = (ToDoListFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_to_do_list);
if(fragment != null){
fragment.setListAdapter(adapter);
}
}

@Override
public void newItemAdd(String contnet) {
//构建数据源
data.add(contnet);
adapter.notifyDataSetChanged();
}
}

//最重要的部分
public class NewItemFragment extends Fragment {

//声明一个接口,定义需要向Activity传递的方法
public interface OnNewItemAddListener{
public void newItemAdd(String contnet);
}

//声明一个接口引用变量
private OnNewItemAddListener onNewItemAddListener;

@Override
public void onAttach(Context context) {
super.onAttach(context);
//要求该Ffragment所附着的Activity必须实现这个方法
onNewItemAddListener = (OnNewItemAddListener) context;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

View view = inflater.inflate(R.layout.new_item_fragment, container, false);
EditText newItem = view.findViewById(R.id.input_text);
newItem.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {

if(keyEvent.getAction() == KeyEvent.ACTION_DOWN){
if(i == KeyEvent.KEYCODE_ENTER){
String content = newItem.getText().toString();
onNewItemAddListener.newItemAdd(content);
newItem.setText("");
return true;
}
}

return false;
}
});
return view;
}
}