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 相关文章推荐
SpringCloud的JPA连接PostgreSql的教程
Jun 26 Java/Android
Java基础-封装和继承
Jul 02 Java/Android
JavaWeb 入门篇(3)ServletContext 详解 具体应用
Jul 16 Java/Android
java设计模式--三种工厂模式详解
Jul 21 Java/Android
java设计模式--七大原则详解
Jul 21 Java/Android
SpringBoot整合Mybatis Generator自动生成代码
Aug 23 Java/Android
Java异常处理try catch的基本用法
Dec 06 Java/Android
Android自定义ScrollView实现阻尼回弹
Apr 01 Java/Android
Spring Boot项目传参校验的最佳实践指南
Apr 05 Java/Android
Spring Data JPA框架自定义Repository接口
Apr 28 Java/Android
详解Flutter自定义应用程序内键盘的实现方法
Jun 14 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
深入理解:单一入口、MVC、ORM、CURD、ActiveRecord概念
2013/06/06 PHP
php开启与关闭错误提示适用于没有修改php.ini的权限
2014/10/16 PHP
PHP四舍五入、取整、round函数使用示例
2015/02/06 PHP
PHPStrom 新建FTP项目以及在线操作教程
2016/10/16 PHP
微信 getAccessToken方法详解及实例
2016/11/23 PHP
基于Laravel实现的用户动态模块开发
2017/09/21 PHP
分析 JavaScript 中令人困惑的变量赋值
2007/08/13 Javascript
图片自动缩小 点击放大
2008/07/07 Javascript
ASP小贴士/ASP Tips javascript tips可以当桌面
2009/12/10 Javascript
js设置组合快捷键/tabindex功能的方法
2013/11/21 Javascript
javascript实现微信分享
2014/12/23 Javascript
浅谈javascript中replace()方法
2015/11/10 Javascript
详解AngularJS中的http拦截
2016/02/09 Javascript
[原创]jQuery常用的4种加载方式分析
2016/07/25 Javascript
JavaScript定义函数_动力节点Java学院整理
2017/06/27 Javascript
ReactNative中使用Redux架构总结
2017/12/15 Javascript
JavaScript实现重力下落与弹性效果的方法分析
2017/12/20 Javascript
Nuxt.js踩坑总结分享
2018/01/18 Javascript
Vue常见面试题整理【值得收藏】
2018/09/20 Javascript
Vue项目打包编译优化方案
2020/09/16 Javascript
Python学习笔记(二)基础语法
2014/06/06 Python
python使用nntp读取新闻组内容的方法
2015/05/08 Python
Python socket 套接字实现通信详解
2019/08/27 Python
Python面向对象之继承原理与用法案例分析
2019/12/31 Python
PyTorch之nn.ReLU与F.ReLU的区别介绍
2020/06/27 Python
美国最受欢迎的度假目的地优惠套餐:BookVIP
2018/09/27 全球购物
DIY蛋糕店的创业计划书范文
2013/12/26 职场文书
工作中个人的自我评价
2013/12/31 职场文书
英语演讲稿范文
2014/01/03 职场文书
教学大赛获奖感言
2014/01/15 职场文书
房地产项目策划书
2014/02/05 职场文书
会计求职自荐信范文
2015/03/04 职场文书
周一早安温馨问候祝福语!
2019/07/15 职场文书
python批量更改目录名/文件名的方法
2021/04/18 Python
一道JS算法面试题——冒泡、选择排序
2021/04/21 Javascript
Go gorilla securecookie库的安装使用详解
2022/08/14 Golang