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 相关文章推荐
Java并发编程之Executor接口的使用
Jun 21 Java/Android
Java集成swagger文档组件
Jun 28 Java/Android
使用Springboot实现健身房管理系统
Jul 01 Java/Android
Springboot配置suffix指定mvc视图的后缀方法
Jul 03 Java/Android
SpringBoot SpringEL表达式的使用
Jul 25 Java/Android
Java8中Stream的一些神操作
Nov 02 Java/Android
解析探秘fescar分布式事务实现原理
Feb 28 Java/Android
Java 超详细讲解IO操作字节流与字符流
Mar 25 Java/Android
Android开发手册TextInputLayout样式使用示例
Jun 10 Java/Android
SpringBoot项目多数据源及mybatis 驼峰失效的问题解决方法
Jul 07 Java/Android
Spring中bean集合注入的方法详解
Jul 07 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
PHPThumb图片处理实例
2014/05/03 PHP
JavaScript 常见对象类创建代码与优缺点分析
2009/12/07 Javascript
AJAX使用了UpdatePanel后无法使用alert弹出脚本
2010/04/02 Javascript
基于JQuery的简单实现折叠菜单代码
2010/09/15 Javascript
教您去掉ie网页加载进度条的方法
2010/12/09 Javascript
JavaScript 放大镜 移动镜片效果代码
2011/05/09 Javascript
JavaScript ECMA-262-3 深入解析.第三章.this
2011/09/28 Javascript
火狐textarea输入法的bug的触发及解决
2013/07/24 Javascript
Ajax同步与异步传输的示例代码
2013/11/21 Javascript
使用jquery清空、复位整个输入域
2015/04/02 Javascript
详解微信小程序——自定义圆形进度条
2016/12/29 Javascript
ES5学习教程之Array对象
2017/04/01 Javascript
老生常谈angularjs中的$state.go
2017/04/24 Javascript
JS库particles.js创建超炫背景粒子插件(附源码下载)
2017/09/13 Javascript
JavaScript图片处理与合成总结
2018/03/04 Javascript
如何解决.vue文件url引用文件的问题
2019/01/18 Javascript
JS如何在数组指定位置插入元素
2020/03/10 Javascript
vue.js实现h5机器人聊天(测试版)
2020/07/16 Javascript
vue实现移动端触屏拖拽功能
2020/08/21 Javascript
以Flask为例讲解Python的框架的使用方法
2015/04/29 Python
Python中type的构造函数参数含义说明
2015/06/21 Python
python访问mysql数据库的实现方法(2则示例)
2016/01/06 Python
用virtualenv建立多个Python独立虚拟开发环境
2017/07/06 Python
Python数字图像处理之霍夫线变换实现详解
2018/01/12 Python
python使用tensorflow深度学习识别验证码
2018/04/03 Python
解决安装tensorflow遇到无法卸载numpy 1.8.0rc1的问题
2018/06/13 Python
Python3实现转换Image图片格式
2018/06/21 Python
python中时间转换datetime和pd.to_datetime详析
2019/08/11 Python
python 如何去除字符串头尾的多余符号
2019/11/19 Python
Python GUI编程学习笔记之tkinter界面布局显示详解
2020/03/30 Python
日本民宿预约平台:STAY JAPAN
2017/07/01 全球购物
物流仓储实习自我鉴定
2013/09/25 职场文书
仓管员岗位职责范文
2013/11/08 职场文书
华清池导游词
2015/02/02 职场文书
python删除csv文件的行列
2021/04/06 Python
配置nginx负载均衡
2022/05/06 Servers