Android使用EventBus多次接收消息

Freya ·
更新时间:2024-11-13
· 1827 次阅读

场景

Fragment中嵌套Fragment,且被嵌套的Fragment是复用的,点击其中item后进入详情,返回后需要回传数据并刷新列表。

由于是Fragment之间的相互嵌套,不方便使用Intent返回数据,也不方便使用callback回调来返回数据,所以选择了使用EventBus发送消息,但是发现在列表中使用EventBus发送消息后,Fragment中接收消息的方法会执行多次。

发送消息:

EventBus.getDefault().post(new TestEvent());

接收消息:

@Subscribe(threadMode = ThreadMode.MAIN)     public void onTestEvent(TestEvent event) {        onSwipeRefresh();     }

也就是onTestEvent方法会被调用多次,数据也会多次刷新。

原因分析

因为Fragment是复用的,而EventBus订阅消息也在复用的Fragment中,导致该消息被多次订阅。以ItemFragment为例。

public class ItemFragment extends Fragment {     private static final String ARG_COLUMN_COUNT = "column-count";     private int mColumnCount = 1;     public ItemFragment() {     }     @SuppressWarnings("unused")     public static ItemFragment newInstance(int columnCount) {         ItemFragment fragment = new ItemFragment();         Bundle args = new Bundle();         args.putInt(ARG_COLUMN_COUNT, columnCount);         fragment.setArguments(args);         return fragment;     }     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         if (getArguments() != null) {             mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);         }     }     @Override     public void onStart() {         super.onStart();         // 订阅消息         EventBus.getDefault().register(this);     }     @Override     public void onStop() {         super.onStop();         // 注销订阅         EventBus.getDefault().unregister(this);     } }

复用ItemFragment:

public class HomeFragment extends Fragment {     private int activeColor = Color.parseColor("#ffffff");     private int normalColor = Color.parseColor("#666666");     private final String[] tabs = new String[]{"第一页", "第二页", "第三页", "第四页", "第五页"};     public View onCreateView(@NonNull LayoutInflater inflater,                              ViewGroup container, Bundle savedInstanceState) {                             ...         vp2.setAdapter(new FragmentStateAdapter(getActivity().getSupportFragmentManager(), getLifecycle()) {             @NonNull             @Override             public Fragment createFragment(int position) {                 return ItemFragment.newInstance(position + 10);             }             @Override             public int getItemCount() {                 return tabs.length;             }         });         ... }

因为创建了5个ItemFragment对象,所以EventBus被订阅了5次,所以消息时也会被接收5次。

解决方案

1、提前在宿主Activity中进行EventBus消息订阅,但是该方法不适合多层级的Fragment嵌套,EventBus订阅不成功,也就接收不到消息。

2、在Fragment中添加标签,识别当前的Fragment。

@Override     public void onStart() {         super.onStart();         // 2 是需要接收消息的Fragment的索引         if(2 == position) {             EventBus.getDefault().register(this);         }     }     @Override     public void onStop() {         super.onStop();         if( 2 == position) {             EventBus.getDefault().unregister(this);         }     }

复用的Fragment中只有索引为2的Fragment才会订阅消息,所以发送消息的时候只有索引为2的Fragment才能接收到消息,也就解决了多次接收消息的问题。

3、消息中添加标记。

@Subscribe(threadMode = ThreadMode.MAIN)     public void onTestEvent(TestEvent event) {         if (event != null) {             // 2 是需要接收消息的Fragment的索引             if(event.getPosition() == 2){                 onSwipeRefresh();             }         }     }

EventBus在post消息的时候,把需要哪一个页面刷新的position发送,接收消息时识别根据索引判断需要哪一个页面刷新。不一定要Fragment的position,只要能唯一识别Fragment就行。



eventbus Android

需要 登录 后方可回复, 如果你还没有账号请 注册新账号