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 相关文章推荐
Spring Data JPA使用JPQL与原生SQL进行查询的操作
Jun 15 Java/Android
Java框架入门之简单介绍SpringBoot框架
Jun 18 Java/Android
浅谈什么是SpringBoot异常处理自动配置的原理
Jun 21 Java/Android
SpringBoot集成Redis,并自定义对象序列化操作
Jun 22 Java/Android
基于Java的MathML转图片的方法(示例代码)
Jun 23 Java/Android
Java面试题冲刺第十九天--数据库(4)
Aug 07 Java/Android
Android基于Fresco实现圆角和圆形图片
Apr 01 Java/Android
Java 数据结构七大排序使用分析
Apr 02 Java/Android
Android Rxjava3 使用场景详解
Apr 07 Java/Android
Java数组详细介绍及相关工具类
Apr 14 Java/Android
Java处理延时任务的常用几种解决方案
Jun 01 Java/Android
httpclient调用远程接口的方法
Aug 14 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
php preg_filter执行一个正则表达式搜索和替换
2012/02/27 PHP
基于session_unset与session_destroy的区别详解
2013/06/03 PHP
Thinkphp无限级分类代码
2015/11/11 PHP
thinkphp隐藏index.php/home并允许访问其他模块的实现方法
2016/10/13 PHP
Yii2.0框架模型添加/修改/删除数据操作示例
2019/07/18 PHP
laravel-admin 管理平台获取当前登陆用户信息的例子
2019/10/08 PHP
10个基于Jquery的幻灯片插件教程
2010/10/29 Javascript
javascript中的previousSibling和nextSibling的正确用法
2015/09/16 Javascript
jQuery插件学习教程之SlidesJs轮播+Validation验证
2016/07/12 Javascript
WEB前端实现裁剪上传图片功能
2016/10/17 Javascript
微信小程序 传值取值的几种方法总结
2017/01/16 Javascript
BootStrap点击保存后实现模态框自动关闭的思路(模态框)
2017/09/26 Javascript
(模仿京东用户注册)用JQuery实现简单表单验证,初学者必看
2018/01/08 jQuery
微信小程序出现wx.getLocation再次授权问题的解决方法分析
2019/01/16 Javascript
5个你不知道的JavaScript字符串处理库(小结)
2020/06/01 Javascript
JS实现小米轮播图
2020/09/21 Javascript
详解JavaScript中的链式调用
2020/11/27 Javascript
[09:23]国际邀请赛采访专栏:iG战队VK,Tongfu战队Cu
2013/08/05 DOTA
[02:53]DOTA2亚洲邀请赛 NewBee战队巡礼
2015/02/03 DOTA
[36:19]2018DOTA2亚洲邀请赛 小组赛 A组加赛 Newbee vs LGD
2018/04/03 DOTA
[48:11]完美世界DOTA2联赛 Magma vs GXR 第二场 11.07
2020/11/10 DOTA
Mac中Python 3环境下安装scrapy的方法教程
2017/10/26 Python
Python requests库用法实例详解
2018/08/14 Python
关于python多重赋值的小问题
2019/04/17 Python
Python数据类型之String字符串实例详解
2019/05/08 Python
详解numpy的argmax的具体使用
2019/05/27 Python
python傅里叶变换FFT绘制频谱图
2019/07/19 Python
python元组和字典的内建函数实例详解
2019/10/22 Python
python异常处理、自定义异常、断言原理与用法分析
2020/03/23 Python
jupyter notebook清除输出方式
2020/04/10 Python
python3.4中清屏的处理方法
2020/07/06 Python
Python faker生成器生成虚拟数据代码实例
2020/07/20 Python
Foreo国际站:Foreo International
2018/10/29 全球购物
瑞士图书网站:Weltbild.ch
2019/09/17 全球购物
基层干部个人对照检查及整改措施
2014/10/28 职场文书
民主生活会汇报材料
2014/12/15 职场文书