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 相关文章推荐
springboot @ConfigurationProperties和@PropertySource的区别
Jun 11 Java/Android
SpringBoot集成Druid连接池连接MySQL8.0.11
Jul 02 Java/Android
JavaWeb 入门:Hello Servlet
Jul 16 Java/Android
SpringBoot SpringEL表达式的使用
Jul 25 Java/Android
正则表达式拆分url实例代码
Feb 24 Java/Android
Java中的随机数Random
Mar 17 Java/Android
Java基于Dijkstra算法实现校园导游程序
Mar 17 Java/Android
Mybatis-Plus进阶分页与乐观锁插件及通用枚举和多数据源详解
Mar 21 Java/Android
Java设计模式中的命令模式
Apr 28 Java/Android
Java 死锁解决方案
May 11 Java/Android
SpringCloud中分析讲解Feign组件添加请求头有哪些坑梳理
Jun 21 Java/Android
MyBatis XPathParser解析器使用范例详解
Jul 15 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
Laravel 5.5 的自定义验证对象/类示例代码详解
2017/08/29 PHP
popdiv
2006/07/14 Javascript
iis6+javascript Add an Extension File
2007/06/13 Javascript
地址栏上的一段语句,改变页面的风格。(教程)
2008/04/02 Javascript
js创建对象的几种常用方式小结(推荐)
2010/10/24 Javascript
jQuery仿Excel表格编辑功能的实现代码
2013/05/01 Javascript
js如何判断不同系统的浏览器类型
2013/10/28 Javascript
JS复制到剪贴板示例代码
2013/10/30 Javascript
js日期、星座的级联显示代码
2014/01/23 Javascript
jquery ajax传递中文参数乱码问题及解决方法说明
2014/02/07 Javascript
Js实现无刷新删除内容
2015/04/29 Javascript
在JS中操作时间之getUTCMilliseconds()方法的使用
2015/06/10 Javascript
Bootstrap学习笔记之css样式设计(2)
2016/06/07 Javascript
javascript设计模式之module(模块)模式
2016/08/19 Javascript
基于Jquery Ajax type的4种类型(详解)
2017/08/02 jQuery
解决html-jquery/js引用外部图片时遇到看不了或出现403的问题
2017/09/22 jQuery
layui之select的option叠加问题的解决方法
2018/03/08 Javascript
详解Vue源码之数据的代理访问
2018/12/11 Javascript
详解基于Vue/React项目的移动端适配方案
2019/08/23 Javascript
Windows下安装 node 的版本控制工具 nvm
2020/02/06 Javascript
Element InputNumber计数器的使用方法
2020/07/27 Javascript
[37:22]DOTA2上海特级锦标赛D组资格赛#2 Liquid VS VP第一局
2016/02/28 DOTA
Python 中urls.py:URL dispatcher(路由配置文件)详解
2017/03/24 Python
Python使用random.shuffle()打乱列表顺序的方法
2018/11/08 Python
Python扫描端口的实现
2021/01/25 Python
Paper Cape官网:美国婴儿和儿童服装品牌
2019/11/02 全球购物
迪卡侬(Decathlon)加拿大官网:源自法国的运动专业超市
2020/11/22 全球购物
实习报告评语
2014/04/26 职场文书
电子商务专业自荐信
2014/06/02 职场文书
经典演讲稿开场白
2014/08/25 职场文书
活动总结新闻稿
2014/08/30 职场文书
乡镇党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
离婚协议书范本2014
2014/10/27 职场文书
第28个世界无烟日活动总结
2015/02/10 职场文书
消防演习感想
2015/08/10 职场文书
导游词之开封禹王台风景区
2019/12/02 职场文书