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
解决SpringCloud Feign传对象参数调用失败的问题
Jun 23 Java/Android
解决SpringBoot跨域的三种方式
Jun 26 Java/Android
springboot 启动如何排除某些bean的注入
Aug 02 Java/Android
简述Java中throw-throws异常抛出
Aug 07 Java/Android
详解Spring Security中的HttpBasic登录验证模式
Mar 17 Java/Android
教你在 Java 中实现 Dijkstra 最短路算法的方法
Apr 08 Java/Android
详细介绍Java中的CyclicBarrier
Apr 13 Java/Android
spring IOC容器的Bean管理XML自动装配过程
May 30 Java/Android
springboot 全局异常处理和统一响应对象的处理方式
Jun 28 Java/Android
Java实现HTML转为Word的示例代码
Jun 28 Java/Android
SpringBoot项目部署到阿里云服务器的实现步骤
Jun 28 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+.htaccess实现全站静态HTML文件GZIP压缩传输(一)
2007/02/15 PHP
火车头discuz6.1 完美采集的php接口文件
2009/09/13 PHP
destoon二次开发模板及调用语法汇总
2014/06/21 PHP
php无限级分类实现评论及回复功能
2019/02/18 PHP
获取Javscript执行函数名称的方法
2006/12/22 Javascript
jquery 操作表格实现代码(多种操作打包)
2011/03/20 Javascript
JavaScript动态修改弹出窗口大小的方法
2015/04/06 Javascript
整理Javascript基础入门学习笔记
2015/11/29 Javascript
深入解析AngularJS框架中$scope的作用与生命周期
2016/03/05 Javascript
jquery动态切换背景图片的简单实现方法
2016/05/14 Javascript
js实现常用排序算法
2016/08/09 Javascript
jquery网页日历显示控件calendar3.1使用详解
2016/11/24 Javascript
详解NodeJs支付宝移动支付签名及验签
2017/01/06 NodeJs
javascript 网页进度条简单实例
2017/02/22 Javascript
selenium+java中用js来完成日期的修改
2019/10/31 Javascript
Vuex中实现数据状态查询与更改
2019/11/08 Javascript
用Python脚本来删除指定容量以上的文件的教程
2015/05/04 Python
在Python中操作时间之tzset()方法的使用教程
2015/05/22 Python
Linux 下 Python 实现按任意键退出的实现方法
2016/09/25 Python
Python中index()和seek()的用法(详解)
2017/04/27 Python
Python MD5加密实例详解
2017/08/02 Python
微信跳一跳游戏python脚本
2020/04/01 Python
python sqlite的Row对象操作示例
2019/09/11 Python
在Django中实现添加user到group并查看
2019/11/18 Python
基于python中__add__函数的用法
2019/11/25 Python
Python3内置函数chr和ord实现进制转换
2020/06/05 Python
浅谈Python中的字符串
2020/06/10 Python
Python如何读取、写入JSON数据
2020/07/28 Python
幼师自荐信范文
2013/10/06 职场文书
毕业生自荐信
2013/12/14 职场文书
《灯光》教学反思
2014/02/08 职场文书
百日安全活动总结
2014/05/04 职场文书
收银员岗位职责
2015/02/03 职场文书
计算机专业自荐信范文
2015/03/26 职场文书
中学社团活动总结
2015/05/07 职场文书
quickjs 封装 JavaScript 沙箱详情
2021/11/02 Javascript