Activity 与 Fragment 通信方式

Posted by pangrongxian on 2017-07-20
Android

Activity 与 Fragment 通信方式

转载请注明出处:Android 解忧杂货店
主页:https://pangrongxian.github.io/

(一)Handler

(二)广播

(三)EventBus

(四)接口回调

(五)Bundle和setArguments(bundle)


通常,Fragment 与 Activity 通信存在三种情形:

  1. Activity 操作内嵌的 Fragment,
  2. Fragment 操作宿主 Activity,
  3. Fragment 操作同属 Activity中的其他 Fragment。

由于 Activity 持有所有内嵌的 Fragment 对象实例。(创建实例时保存的 Fragment 对象,或者通过 FragmentManager 类提供的findFragmentById()和findFragmentByTag() 方法也能获取到 Fragment 对象),所以可以直接操作Fragment。Fragment 通过 getActivity() 方法可以获取到宿主 Activity 对象(强制转换类型即可),进而可以操作宿主 Activity;那么很自然的,获取到宿主 Activity 对象的 Fragment 便可以操作其他Fragment 对象。

虽然上述操作已经能够解决 Activity 与 Fragment 的通信问题,但会造成代码逻辑紊乱的结果,极度不符合这一编程思想:高内聚,低耦合。Fragment 做好自己的事情即可,所有涉及到 Fragment 之间的控制显示等操作,都应交由宿主 Activity 来统一管理。

(一)Handler

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 MainActivity extends FragmentActivity{
//声明一个Handler
public Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
...相应的处理代码
}
}
...相应的处理代码
}
public class MainFragment extends Fragment{
//保存Activity传递的handler
private Handler mHandler;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
//这个地方已经产生了耦合,若还有其他的activity,这个地方就得修改
if(activity instance MainActivity){
mHandler = ((MainActivity)activity).mHandler;
}
}
...相应的处理代码
}
  • Fragment对具体的Activity存在耦合,不利于Fragment复用
  • 不利于维护,若想删除相应的Activity,Fragment也得改动
  • 没法获取Activity的返回数据

(二)广播

在 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
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(ACTION_NAME)) {
String msg = intent.getStringExtra("msg");
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
}
};
public void registerBoradcastReceiver() {
IntentFilter myIntentFilter = new IntentFilter();
myIntentFilter.addAction(ACTION_NAME);
registerReceiver(mBroadcastReceiver, myIntentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mBroadcastReceiver);
}

(三)EventBus

MainActivity

1.注册订阅者(事件接收者)

1
EventBus.getDefault().register(this);
1
2
3
4
5
6
7
8
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,
SecondActivity.class);
startActivity(intent);
}
});

2.定义处理接收方法(事件处理)

1
2
3
4
5
@Subscribe
public void onEventMainThread(UserEvent event) {
btn.setText(event.getUserName());
service_tv.setText(event.getUserName());
}

SecondActivity

3.发送事件

1
2
3
4
5
6
7
8
9
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final UserEvent ue = new UserEvent();
ue.setUserName("庞大帅");
EventBus.getDefault().post(ue);
finish();
}
});

(四)接口回调

  1. 在 Fragment 中定义一个接口
  2. 调用接口中的抽象方法
  3. 在 Activity 中实现接口,并具体实现接口中的方法,完成通信。
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
public class MainFragment extends Fragment{
public FragmentListener mListener;
//MainFragment开放的接口
public static interface FragmentListener{
//跳到h5页面
void toH5Page();
//展示消息
void showMsg(String str);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
//对传递进来的Activity进行接口转换
if(activity instance FragmentListener){
mListener = ((FragmentListener)activity);
}
}
...其他处理代码省略
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
msgListener.showMsg("Hello 传递数据给Activity展示");
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
// MainActivity 实现 MainFragment开放的接口
public class MainActivity extends FragmentActivity implements FragmentListener{
@override
public void toH5Page(){... }
@Override
public void showMsg(String str) {
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
...其他处理代码省略
}

(五)Bundle和setArguments(bundle)

  • Fragment 从Activity获取数据

在Fragment 中的 getInstance() 方法中 setArguments() 设置参数

1
2
3
4
5
6
7
public static Fragment getInstance(String msg){
Bundle bundle = new Bundle();
bundle.putString("msg",msg);
MainFragment fragment=new MainFragment();
fragment.setArguments(bundle);
return fragment;
}

再通过getArguments()方法获取数据

1
2
3
4
5
6
7
public void initDatas() {
Bundle bundle = getArguments();
if(bundle!=null){
String msg=bundle.getString("msg");
Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show();
}
}

Activity 中,在创建Fragment对象的时候,调用Fragment的getInstance方法获取对象,并传递参数。

1
2
3
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_main,MainFragment.getInstance("msg"))
.commit();

补充:

Fragment && Fragment 数据交互

Fragment和Fragment间数据交互,应该也是会经常用到的。第一时间,我们可能本能地会想到使用宿主Activity做传递媒介。原理其实也是通过使用onActivityResult回调,完成Fragment && Fragment 的数据交互,这其中有两个比较重要的方法:Fragment.setTargetFragment、getTargetFragment()。

在 FirstFragment 中,通过setTargetFragment来连接需要交互的Fragment

1
secondFragment.setTargetFragment(FirstFragment.this, REQUEST_CODE);

接着实现onActivityResult,处理传递过来的数据

1
2
3
4
5
6
7
8
9
10
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode != Activity.RESULT_OK){
return;
}else{
Integer str = data.getIntExtra("key",-1);
//处理数据...
}
}

在 SecondFragment 中:调用sendResult()方法,回传数据给 FirstFragment

1
2
3
4
5
6
7
8
9
private void sendResult(int resultOk) {
if(getTargetFragment() == null){
return;
}else{
Intent intent = new Intent();
intent.putExtra("key", 520);
getTargetFragment().onActivityResult(FirstFragment.REQUEST_CODE,resultOk,intent);
}
}

Comments: