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

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

