Android使用EventBus多次接收消息
場景
Fragment中嵌套Fragment,且被嵌套的Fragment是復(fù)用的,點擊其中item后進(jìn)入詳情,返回后需要回傳數(shù)據(jù)并刷新列表。

由于是Fragment之間的相互嵌套,不方便使用Intent返回數(shù)據(jù),也不方便使用callback回調(diào)來返回數(shù)據(jù),所以選擇了使用EventBus發(fā)送消息,但是發(fā)現(xiàn)在列表中使用EventBus發(fā)送消息后,F(xiàn)ragment中接收消息的方法會執(zhí)行多次。
發(fā)送消息:
EventBus.getDefault().post(new TestEvent());
接收消息:
@Subscribe(threadMode = ThreadMode.MAIN)
? ? public void onTestEvent(TestEvent event) {
? ? ? ?onSwipeRefresh();
? ? }也就是onTestEvent方法會被調(diào)用多次,數(shù)據(jù)也會多次刷新。
原因分析
因為Fragment是復(fù)用的,而EventBus訂閱消息也在復(fù)用的Fragment中,導(dǎo)致該消息被多次訂閱。以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);
? ? }
}復(fù)用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;
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? ...
}因為創(chuàng)建了5個ItemFragment對象,所以EventBus被訂閱了5次,所以消息時也會被接收5次。
解決方案
1、提前在宿主Activity中進(jìn)行EventBus消息訂閱,但是該方法不適合多層級的Fragment嵌套,EventBus訂閱不成功,也就接收不到消息。
2、在Fragment中添加標(biāo)簽,識別當(dāng)前的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);
? ? ? ? }
? ? }復(fù)用的Fragment中只有索引為2的Fragment才會訂閱消息,所以發(fā)送消息的時候只有索引為2的Fragment才能接收到消息,也就解決了多次接收消息的問題。
3、消息中添加標(biāo)記。
@Subscribe(threadMode = ThreadMode.MAIN)
? ? public void onTestEvent(TestEvent event) {
? ? ? ? if (event != null) {
? ? ? ? ? ? // 2 是需要接收消息的Fragment的索引
? ? ? ? ? ? if(event.getPosition() == 2){
? ? ? ? ? ? ? ? onSwipeRefresh();
? ? ? ? ? ? }
? ? ? ? }
? ? }EventBus在post消息的時候,把需要哪一個頁面刷新的position發(fā)送,接收消息時識別根據(jù)索引判斷需要哪一個頁面刷新。不一定要Fragment的position,只要能唯一識別Fragment就行。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android開發(fā)之自定義view實現(xiàn)通訊錄列表A~Z字母提示效果【附demo源碼下載】
這篇文章主要介紹了Android開發(fā)之自定義view實現(xiàn)通訊錄列表A~Z字母提示效果,結(jié)合完整實例形式分析了Android獲取通訊錄列表及采用自定義view排列顯示的相關(guān)操作技巧,需要的朋友可以參考下2017-07-07
Android中利用zxing實現(xiàn)自己的二維碼掃描識別詳解
這篇文章主要給大家介紹了關(guān)于Android中利用zxing實現(xiàn)自己的二維碼掃描識別的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用zxing具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-09-09
android surfaceView實現(xiàn)播放視頻功能
這篇文章主要為大家詳細(xì)介紹了android surfaceView實現(xiàn)播放視頻功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-05-05
Android?RxJava與Retrofit結(jié)合使用詳解
RxJava和Retrofit的結(jié)合使用估計已經(jīng)相當(dāng)普遍了,自己工作中也是一直都在使用。在使用的過程中我們都會對其進(jìn)行封裝使用,GitHub上也有很多封裝好的項目可以直接拿來使用,其實對于開源框架的二次封裝有時候針對不同的業(yè)務(wù)邏輯封裝的過程中也多多少少有些不同2023-03-03
Android的權(quán)限設(shè)置及自啟動設(shè)置方法
今天小編就為大家分享一篇Android的權(quán)限設(shè)置及自啟動設(shè)置方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07

