Android使用EventBus发送消息,Fragment中接收消息的方法会执行多次


Posted in Java/Android onApril 24, 2022

场景

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

Android使用EventBus发送消息,Fragment中接收消息的方法会执行多次

由于是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就行。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。


Tags in this post...

Java/Android 相关文章推荐
浅析NIO系列之TCP
Jun 15 Java/Android
Netty结合Protobuf进行编解码的方法
Jun 26 Java/Android
分析并发编程之LongAdder原理
Jun 29 Java/Android
SpringBoot集成Druid连接池连接MySQL8.0.11
Jul 02 Java/Android
Java中CyclicBarrier和CountDownLatch的用法与区别
Aug 23 Java/Android
Java spring定时任务详解
Oct 05 Java/Android
剑指Offer之Java算法习题精讲二叉树的构造和遍历
Mar 21 Java/Android
Java Spring Boot 正确读取配置文件中的属性的值
Apr 20 Java/Android
Spring Data JPA框架自定义Repository接口
Apr 28 Java/Android
java版 简单三子棋游戏
May 04 Java/Android
Android学习之BottomSheetDialog组件的使用
Jun 21 Java/Android
Java Redisson多策略注解限流
Sep 23 Java/Android
Spring Boot 使用 Spring-Retry 进行重试框架
Apr 24 #Java/Android
Android在Sqlite3中的应用及多线程使用数据库的建议
Apr 24 #Java/Android
Android开发 使用文件储存的方式保存QQ密码
Apr 24 #Java/Android
IDEA 2022 Translation 未知错误 翻译文档失败
Android开发实现极为简单的QQ登录页面
Flutter Navigator 实现路由传递参数
Apr 22 #Java/Android
SpringBoot 集成短信和邮件 以阿里云短信服务为例
You might like
备份mysql数据库的php代码(一个表一个文件)
2010/05/28 PHP
ajax php传递和接收变量实现思路及代码
2012/12/19 PHP
探讨php中header的用法详解
2013/06/07 PHP
解析php开发中的中文编码问题
2013/08/08 PHP
PHP中UNIX时间戳和日期间的转换与计算实例
2014/11/19 PHP
php实现高效获取图片尺寸的方法
2014/12/12 PHP
PHP中Session可能会引起并发问题
2015/06/26 PHP
ThinkPHP实现转换数据库查询结果数据到对应类型的方法
2017/11/16 PHP
PHP验证类的封装与使用方法详解
2019/01/10 PHP
JavaScript this 深入理解
2009/07/30 Javascript
实现连缀调用的map方法(prototype)
2009/08/05 Javascript
javascript小数计算出现近似值的解决办法
2010/02/06 Javascript
JQuery 常用操作代码
2010/03/14 Javascript
js中substring和substr的定义和用法
2014/05/05 Javascript
JavaScript中rem布局在react中的应用
2015/12/09 Javascript
js格式化输入框内金额、银行卡号
2016/02/01 Javascript
JS实现iframe编辑器光标位置插入内容的方法(兼容IE和Firefox)
2016/06/24 Javascript
vue2.0嵌套路由实现豆瓣电影分页功能(附demo)
2017/03/13 Javascript
javascript 日期相减-在线教程(附代码)
2017/08/17 Javascript
高性能的javascript之加载顺序与执行原理篇
2018/01/14 Javascript
vue.js 使用axios实现下载功能的示例
2018/03/05 Javascript
说说如何使用Vuex进行状态管理(小结)
2019/04/14 Javascript
[01:14]3.19DOTA2发布会 三代刀塔人第二代
2014/03/25 DOTA
详解Python locals()的陷阱
2019/03/26 Python
Django中reverse反转并且传递参数的方法
2019/08/06 Python
python画微信表情符的实例代码
2019/10/09 Python
python实现手势识别的示例(入门)
2020/04/15 Python
python 常用日期处理-- datetime 模块的使用
2020/09/02 Python
巴西体育用品商店:Lojão dos Esportes
2018/07/21 全球购物
美国修容界大佬创建的个人美妆品牌:Kevyn Aucoin Beauty
2018/12/12 全球购物
自我评价范文
2013/12/22 职场文书
创业计划书——互联网商机
2014/01/12 职场文书
小学生优秀评语
2014/12/29 职场文书
检讨书之工作不认真
2019/08/14 职场文书
oracle表分区的概念及操作
2021/04/24 Oracle
详解Python生成器和基于生成器的协程
2021/06/03 Python