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 Shutdown Hook场景使用及源码分析
Jun 15 Java/Android
Spring Cloud Gateway去掉url前缀
Jul 15 Java/Android
Java spring定时任务详解
Oct 05 Java/Android
Java异常处理try catch的基本用法
Dec 06 Java/Android
Java中try catch处理异常示例
Dec 06 Java/Android
maven依赖的version声明控制方式
Jan 18 Java/Android
Spring this调用当前类方法无法拦截的示例代码
Mar 20 Java/Android
springboot入门 之profile设置方式
Apr 04 Java/Android
openGauss数据库JDBC环境连接配置的详细过程(Eclipse)
Jun 01 Java/Android
Java实现超大Excel文件解析(XSSF,SXSSF,easyExcel)
Jul 15 Java/Android
OpenFeign实现远程调用
Aug 14 Java/Android
Java使用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 文件上传实例代码
2012/04/19 PHP
PHP接口并发测试的方法(推荐)
2016/12/15 PHP
支持汉转拼和拼音分词的PHP中文工具类ChineseUtil
2018/02/23 PHP
jQuery 1.5最新版本的改进细节分析
2011/01/19 Javascript
Javascript获取HTML静态页面参数传递值示例
2013/08/18 Javascript
js转义字符介绍
2013/11/05 Javascript
js window.onload 加载多个函数和追加函数详解
2014/01/08 Javascript
Vue.js每天必学之数据双向绑定
2016/09/05 Javascript
jQuery源码分析之init的详细介绍
2017/02/13 Javascript
canvas 绘制圆形时钟
2017/02/22 Javascript
解决vue router使用 history 模式刷新后404问题
2017/07/19 Javascript
webpack写jquery插件的环境配置
2017/12/21 jQuery
Bootstrap实现可折叠分组侧边导航菜单
2018/03/07 Javascript
基于JS开发微信网页录音功能的实例代码
2019/04/30 Javascript
vue 扩展现有组件的操作
2020/08/14 Javascript
Vue 实现一个简单的鼠标拖拽滚动效果插件
2020/12/10 Vue.js
Python 列表list使用介绍
2014/11/30 Python
Python生成随机MAC地址
2015/03/10 Python
Selenium Webdriver元素定位的八种常用方式(小结)
2021/01/13 Python
基于Html5实现的语音搜索功能
2019/05/13 HTML / CSS
伦敦时尚生活的缩影:LN-CC
2017/01/24 全球购物
怀旧收藏品和经典纪念品:Betty’s Attic
2018/08/29 全球购物
应届生简历中的自我评价
2014/01/13 职场文书
小学教研工作制度
2014/01/15 职场文书
中学生差生评语
2014/01/30 职场文书
广告设计应届生求职信
2014/03/01 职场文书
财务总监岗位职责
2014/03/07 职场文书
遗嘱公证书标准样本
2014/04/08 职场文书
学校安全责任书
2014/04/14 职场文书
小学生一分钟演讲稿
2014/08/26 职场文书
学校联谊协议书
2014/09/16 职场文书
2015学生会文艺部工作总结
2015/04/03 职场文书
《折线统计图》教学反思
2016/02/22 职场文书
Mysql Online DDL的使用详解
2021/05/20 MySQL
ORACLE查看当前账号的相关信息
2021/06/18 Oracle
MySQL库表太大怎么办? 数据库分库分表项目实践
2022/04/11 MySQL