Android 使用EventBus进行Fragment和Activity通信
本文介绍EventBus的基本使用,以及用于Fragment和Activity之间通信。
github地址: https://github.com/greenrobot/EventBus 版本是 EventBus-2.4.0 release
EventBus是基于订阅和发布的一种通信机制,使用流程如下:
- 实例化EventBus对象
- 注册订阅者
- 发布消息
- 接受消息
对应代码
EventBus eventBus = new EventBus(); eventBus.register(subscriber object);//注册订阅者 订阅者对象中必须有 onEvent public 方法 public void onEvent(Object event){ //接收消息 } eventBus.post(event);//发送消息
应用到Activity和Fragment中
因为订阅者必须有onEvent方法,因此我们创建一个基类让onEvent方法作为抽象方法
public abstract class BaseFragment extends Fragment { public BaseFragment() { } public abstract void onEvent(MyEvent eventData); }
MainActivity
public class MainActivity extends FragmentActivity { public Button btn; public EventBus eventBus; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button) findViewById(R.id.btn); eventBus = new EventBus(); FragmentManager fm = getSupportFragmentManager(); MyFragment myFragment = new MyFragment(); fm.beginTransaction().replace(R.id.container, myFragment).commit(); eventBus.register(myFragment);//注册订阅者 MyFragment btn.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { List<String> list = new ArrayList<String>(); list.add("test string"); MyEvent myEvent = new MyEvent(); myEvent.eventType = 1; myEvent.data = list; eventBus.post(myEvent);//发布消息 myEvent = new MyEvent(); myEvent.eventType = 2; myEvent.data = new MyCallBack();//接口回调作为引用 eventBus.post(myEvent);//发布消息 } }); } //此时MainActivity作为订阅者 public void onEvent(MyEvent event) { Log.d("", "onEvent >> callback main>>>" + event.data); } //回调接口也可以做为事件数据 class MyCallBack implements DataCallBack { @Override public void onCallback(MyEvent eventData) { Log.d("", "eventData >>>> " + eventData); } } }
封装的消息MyEvent
public class MyEvent { public MyEvent() { } public int eventType;//可能类型有很多种,数据也不一样 public Object data;//数据对象 }
MyFragment
public class MyFragment extends BaseFragment { private DataCallBack actCallback; private EventBus eventBus; public MyFragment() { setHasOptionsMenu(true); eventBus = new EventBus(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_main, null); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { view.findViewById(R.id.call).setOnClickListener(new OnClickListener() { public void onClick(View view) { if (actCallback != null) { //得到接口后 回调一下 MyEvent event = new MyEvent(); event.data = "this is fragment:" + MyFragment.this; actCallback.onCallback(event);//调用回调 } } }); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (getActivity() != null) { eventBus.register(getActivity());//事件订阅者注册,订阅者为MainActivity } } @Override public void onEvent(MyEvent event) { int type = event.eventType; if (type == 1) { Log.d("", "onEvent type 1:" + event.data); } else if (type == 2) { Log.d("", "onEvent type 2:" + (event.data instanceof DataCallBack)); if (event.data instanceof DataCallBack) { actCallback = ((DataCallBack) event.data);//得到回调 //发消息给MainActivity MyEvent event2 = new MyEvent(); event2.data = "call main activity method"; eventBus.post(event2);//发布消息 } } } }
一般让Fragment调用Activity的方法有一下几种
- 创建Fragment的时候把MainActivity引用传给Fragment,其实通过getActivity()也能获取到实例
- 创建Fragment的时候传入一个Handler实例,在Fragment中sendMessage也是可以的
- 创建Fragment的时候传入一个实例化接口,作为回调
我觉得用接口的方式更加好,耦合性算是比较低的一种。当Fragment pop后 getActivity()获取的引用为NULL,传入Handler实例是可以的,但有些时候你可能用不上Handler这个东西。
EventBus使用还是比较简单的,降低了代码耦合性,只需要在onEvent中处理数据即可。