Android使用EventBus多次接收消息
場(chǎng)景
Fragment中嵌套Fragment,且被嵌套的Fragment是復(fù)用的,點(diǎn)擊其中item后進(jìn)入詳情,返回后需要回傳數(shù)據(jù)并刷新列表。
由于是Fragment之間的相互嵌套,不方便使用Intent返回?cái)?shù)據(jù),也不方便使用callback回調(diào)來返回?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(); ? ? ? ? // 注銷訂閱 ? ? ? ? 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; ? ? ? ? ? ? } ? ? ? ? }); ? ? ? ? ... }
因?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才能接收到消息,也就解決了多次接收消息的問題。
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è)頁面刷新的position發(fā)送,接收消息時(shí)識(shí)別根據(jù)索引判斷需要哪一個(gè)頁面刷新。不一定要Fragment的position,只要能唯一識(shí)別Fragment就行。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
android設(shè)備間實(shí)現(xiàn)無線投屏的示例代碼
Android提供了MediaProjection來實(shí)現(xiàn)錄屏,通過MediaProjection可以獲取當(dāng)前屏幕的視頻流,而視頻流需要通過編解碼來壓縮進(jìn)行傳輸,通過MediaCodec可實(shí)現(xiàn)視頻的編碼和解碼,這篇文章主要介紹了android設(shè)備間實(shí)現(xiàn)無線投屏,需要的朋友可以參考下2022-06-06Android編程實(shí)現(xiàn)調(diào)用系統(tǒng)分享功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)調(diào)用系統(tǒng)分享功能,結(jié)合實(shí)例形式分析了Android實(shí)現(xiàn)針對(duì)文字、圖片等元素分享功能的相關(guān)操作技巧,需要的朋友可以參考下2017-01-01Android EditText默認(rèn)不彈出輸入法的實(shí)現(xiàn)方法
下面小編就為大家分享一篇Android EditText默認(rèn)不彈出輸入法的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01Android自定義圓弧進(jìn)度條加數(shù)字動(dòng)態(tài)變化
這篇文章主要為大家詳細(xì)介紹了Android自定義圓弧進(jìn)度條加數(shù)字動(dòng)態(tài)變化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07Android編程實(shí)現(xiàn)類似天氣預(yù)報(bào)圖文字幕垂直滾動(dòng)效果的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)類似天氣預(yù)報(bào)圖文字幕垂直滾動(dòng)效果的方法,涉及Android基于布局及事件響應(yīng)實(shí)現(xiàn)圖文滾動(dòng)效果的相關(guān)操作技巧,需要的朋友可以參考下2017-08-08Android模擬器接收UDP數(shù)據(jù)包的若干問題分析
這篇文章主要介紹了Android模擬器接收UDP數(shù)據(jù)包的若干問題,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android模擬器接收UDP數(shù)據(jù)的使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-04-04Android編程之內(nèi)存溢出解決方案(OOM)實(shí)例總結(jié)
這篇文章主要介紹了Android編程之內(nèi)存溢出解決方案(OOM),結(jié)合實(shí)例實(shí)例總結(jié)分析了Android編程過程中常見的內(nèi)存溢出情況與對(duì)應(yīng)的解決方法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11Android 微信搖一搖功能實(shí)現(xiàn)詳細(xì)介紹
這篇文章主要介紹了Android 微信搖一搖功能實(shí)現(xiàn)詳細(xì)介紹的相關(guān)資料,并附實(shí)例代碼及實(shí)現(xiàn)微信搖一搖的思路,需要的朋友可以參考下2016-11-11Android 性能優(yōu)化系列之bitmap圖片優(yōu)化
在日常開發(fā)的APP,大部分時(shí)候需要想用戶展示圖片信息,圖片最終對(duì)應(yīng)Android中的Bitmap對(duì)象。而對(duì)于APP端來說Bitmap又是一個(gè)比較麻煩的問題,主要表現(xiàn)在Bitmap是非常占用內(nèi)存的對(duì)象,處理不當(dāng)將導(dǎo)致APP運(yùn)行卡頓甚至出現(xiàn)OOM2021-11-11