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循环队列与非循环队列的区别总结
Jun 22 Java/Android
Java实现多线程聊天室
Jun 26 Java/Android
解决Swagger2返回map复杂结构不能解析的问题
Jul 02 Java/Android
java解析XML详解
Jul 09 Java/Android
Java实现房屋出租系统详解
Oct 05 Java/Android
springboot如何接收application/x-www-form-urlencoded类型的请求
Nov 02 Java/Android
JavaWeb实现显示mysql数据库数据
Mar 19 Java/Android
Spring this调用当前类方法无法拦截的示例代码
Mar 20 Java/Android
Spring Boot 底层原理基础深度解析
Apr 03 Java/Android
Java版 单机五子棋
May 04 Java/Android
Android studio 简单计算器的编写
May 20 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的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法
2015/10/20 PHP
php提取微信账单的有效信息
2018/10/01 PHP
PHP实现微信小程序用户授权的工具类示例
2019/03/05 PHP
javascript 简单抽屉效果的实现代码
2010/03/09 Javascript
JS隐藏参数post传值实例
2013/04/18 Javascript
JS中把字符转成ASCII值的函数示例代码
2013/11/21 Javascript
下拉框select的绑定示例
2014/09/04 Javascript
zepto.js中tap事件阻止冒泡的实现方法
2015/02/12 Javascript
AngularJS进行性能调优的7个建议
2015/12/28 Javascript
JavaScript对象数组如何按指定属性和排序方向进行排序
2016/06/15 Javascript
jQuery实现圣诞节礼物传送(花式轮播)
2016/12/25 Javascript
Ionic3 UI组件之Gallery Modal详解
2017/06/07 Javascript
解决vue router使用 history 模式刷新后404问题
2017/07/19 Javascript
浅谈nodejs中的类定义和继承的套路
2017/07/26 NodeJs
关于Angularjs中自定义指令一些有价值的细节和技巧小结
2018/04/22 Javascript
JSON数据中存在单个转义字符“\”的处理方法
2018/07/11 Javascript
使用vue-router与v-if实现tab切换遇到的问题及解决方法
2018/09/07 Javascript
微信小程序缓存过期时间的使用详情
2019/05/12 Javascript
jQuery实现轮播图效果
2019/11/26 jQuery
[54:25]Ti4 循环赛第三日LGD vs MOUZ
2014/07/12 DOTA
python Django模板的使用方法
2016/01/14 Python
pyenv命令管理多个Python版本
2017/03/26 Python
详解Python中where()函数的用法
2018/03/27 Python
Python查找不限层级Json数据中某个key或者value的路径方式
2020/02/27 Python
pytorch快速搭建神经网络_Sequential操作
2020/06/17 Python
深入浅析python 中的self和cls的区别
2020/06/20 Python
Python Request类源码实现方法及原理解析
2020/08/17 Python
解决CSS3的opacity属性带来的层叠顺序问题
2016/05/09 HTML / CSS
关于HTML5的22个初级技巧(图文教程)
2012/06/21 HTML / CSS
匈牙利墨盒和碳粉购买网站:CDRmarket
2018/04/14 全球购物
澳大利亚最便宜的网上药房:Chemist Warehouse
2020/01/30 全球购物
神话般的珠宝:Ross-Simons
2020/07/13 全球购物
某/etc/fstab文件中的某行如下: /dev/had5 /mnt/dosdata msdos defaults,usrquota 1 2 请解释其含义
2013/09/18 面试题
销售代表求职自荐信
2013/10/01 职场文书
《三顾茅庐》教学反思
2014/04/10 职场文书
幼儿园大班教师个人总结
2015/02/05 职场文书