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实战之用Swing实现通讯录管理系统
Jun 13 Java/Android
spring cloud gateway中如何读取请求参数
Jul 15 Java/Android
springboot集成springCloud中gateway时启动报错的解决
Jul 16 Java/Android
JVM钩子函数的使用场景详解
Aug 23 Java/Android
Java网络编程之UDP实现原理解析
Sep 04 Java/Android
Java异常处理try catch的基本用法
Dec 06 Java/Android
Java基于Dijkstra算法实现校园导游程序
Mar 17 Java/Android
Spring Boot配合PageHelper优化大表查询数据分页
Apr 20 Java/Android
Java 轮询锁使用时遇到问题
May 11 Java/Android
Android Canvas绘制文字横纵向对齐
Jun 05 Java/Android
springboot集成redis存对象乱码的问题及解决
Jun 16 Java/Android
Springboot集成kafka高级应用实战分享
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批量更改数据库表前缀实现方法
2013/10/26 PHP
php生成图形(Libchart)实例
2013/11/06 PHP
去除php注释和去除空格函数分享
2014/03/13 PHP
ThinkPHP实现简单登陆功能
2017/04/28 PHP
PHP实现数组向任意位置插入,删除,替换数据操作示例
2019/04/05 PHP
用JavaScript实现UrlEncode和UrlDecode的脚本代码
2008/07/23 Javascript
22点关于jquery性能优化的建议
2014/05/28 Javascript
纯css实现窗户玻璃雨滴逼真效果
2015/08/23 Javascript
NodeJs的优势和适合开发的程序
2016/08/14 NodeJs
Javascript 两种刷新方法以及区别和适用范围
2017/01/17 Javascript
Vue.js实战之组件的进阶
2017/04/04 Javascript
解决vue+webpack打包路径的问题
2018/03/06 Javascript
一个Vue页面的内存泄露分析详解
2018/06/25 Javascript
解决vue单页路由跳转后scrollTop的问题
2018/09/03 Javascript
浅谈Vue页面级缓存解决方案feb-alive(上)
2019/04/14 Javascript
JSON是什么?有哪些优点?JSON和XML的区别?
2019/04/29 Javascript
[42:24]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第一场 11.01
2020/11/02 DOTA
python使用xauth方式登录饭否网然后发消息
2014/04/11 Python
Python守护进程和脚本单例运行详解
2017/01/06 Python
python函数式编程学习之yield表达式形式详解
2018/03/25 Python
Python 类,property属性(简化属性的操作),@property,property()用法示例
2019/10/12 Python
Pandas+Matplotlib 箱式图异常值分析示例
2019/12/09 Python
python列表返回重复数据的下标
2020/02/10 Python
Python numpy多维数组实现原理详解
2020/03/10 Python
python3 logging日志封装实例
2020/04/08 Python
Python执行时间的几种计算方法
2020/07/31 Python
采购文员岗位职责
2013/11/20 职场文书
给老婆的婚前保证书
2014/02/01 职场文书
优秀团队获奖感言
2014/02/19 职场文书
创建青年文明号材料
2014/05/09 职场文书
2014年廉洁自律承诺书
2014/05/26 职场文书
代收款委托书范本
2014/10/01 职场文书
辞职书格式样本
2015/02/26 职场文书
我是特种兵观后感
2015/06/11 职场文书
详解CSS玩转图片Base64编码
2021/05/25 HTML / CSS
适合后台管理系统开发的12个前端框架(小结)
2021/06/29 Javascript