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 相关文章推荐
深入理解以DEBUG方式线程的底层运行原理
Jun 21 Java/Android
springboot如何初始化执行sql语句
Jun 22 Java/Android
每日六道java新手入门面试题,通往自由的道路
Jun 30 Java/Android
详解Spring Boot使用系统参数表提升系统的灵活性
Jun 30 Java/Android
用Java实现简单计算器功能
Jul 21 Java/Android
Logback 使用TurboFilter实现日志级别等内容的动态修改操作
Aug 30 Java/Android
java协程框架quasar和kotlin中的协程对比分析
Feb 24 Java/Android
Java 使用类型为Object的变量指向任意类型的对象
Apr 13 Java/Android
Android 中的类文件和类加载器详情
Jun 05 Java/Android
详解Spring Bean的配置方式与实例化
Jun 10 Java/Android
tree shaking对打包体积优化及作用
Jul 07 Java/Android
Java Spring读取和存储详细操作
Aug 05 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
thinkphp修改配置进入默认首页的方法
2017/02/07 PHP
PHP删除数组中指定值的元素常用方法实例分析【4种方法】
2018/08/21 PHP
PHP+Ajax实现的检测用户名功能简单示例
2019/02/12 PHP
PHP设计模式之命令模式示例详解
2020/12/20 PHP
stream.js 一个很小、完全独立的Javascript类库
2011/10/28 Javascript
jquery禁用右键单击功能屏蔽F5刷新
2014/03/17 Javascript
使用ajaxfileupload.js实现ajax上传文件php版
2014/06/26 Javascript
仿百度联盟对联广告实现代码
2014/08/30 Javascript
Jquery中find与each方法用法实例
2015/02/04 Javascript
jQuery实现的跨容器无缝拖动效果代码
2016/06/21 Javascript
js中获取jsp表单中radio类型的值简单实例
2016/08/15 Javascript
windows下vue-cli导入bootstrap样式
2017/04/25 Javascript
vue-cli构建项目使用 less的方法
2017/10/04 Javascript
浅谈vue项目重构技术要点和总结
2018/01/23 Javascript
详解angular脏检查原理及伪代码实现
2018/06/08 Javascript
vue实现todolist基本功能以及数据存储功能实例详解
2019/04/11 Javascript
ES6 Object方法扩展的应用实例分析
2019/06/25 Javascript
JavaScript实现图片上传并预览并提交ajax
2019/09/30 Javascript
这15个Vue指令,让你的项目开发爽到爆
2019/10/11 Javascript
[55:44]OG vs NAVI 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
python中os操作文件及文件路径实例汇总
2015/01/15 Python
Ruby元编程基础学习笔记整理
2016/07/02 Python
Python对列表中的各项进行关联详解
2017/08/15 Python
Python callable()函数用法实例分析
2018/03/17 Python
详解Python的三种可变参数
2019/05/08 Python
Python实现操纵控制windows注册表的方法分析
2019/05/24 Python
Python函数参数定义及传递方式解析
2020/06/10 Python
PyTorch安装与基本使用详解
2020/08/31 Python
html5+css3之制作header实例与更新
2020/12/21 HTML / CSS
一文彻底解决HTML5页面中长按保存图片功能
2019/06/10 HTML / CSS
大学校运会广播稿
2014/02/03 职场文书
教师个人剖析材料
2014/02/05 职场文书
大学活动总结模板
2014/07/10 职场文书
基层党组织建设整改方案
2014/09/16 职场文书
springmvc直接不经过controller访问WEB-INF中的页面问题
2022/02/24 Java/Android
Python绘制散点图之可视化神器pyecharts
2022/07/07 Python