Android EventBus多次接收消息
阿pin 人气:0场景
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就行。
加载全部内容