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中重写父类方法加不加@Override详解
Jun 21 Java/Android
Spring中bean的生命周期之getSingleton方法
Jun 30 Java/Android
java实现对Hadoop的操作
Jul 01 Java/Android
SpringBoot读取Resource下文件的4种方法
Jul 02 Java/Android
SpringBoot整合Mybatis Generator自动生成代码
Aug 23 Java/Android
JAVA API 实用类 String详解
Oct 05 Java/Android
Java8中接口的新特性使用指南
Nov 01 Java/Android
maven依赖的version声明控制方式
Jan 18 Java/Android
Spring依赖注入多种类型数据的示例代码
Mar 31 Java/Android
Java 通过手写分布式雪花SnowFlake生成ID方法详解
Apr 07 Java/Android
Android基础入门之dataBinding的简单使用教程
Jun 21 Java/Android
java.util.NoSuchElementException原因及两种解决方法
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
其他功能
2006/10/09 PHP
FireFox浏览器使用Javascript上传大文件
2013/10/30 PHP
php发送post请求函数分享
2014/03/06 PHP
Yii2使用小技巧之通过 Composer 添加 FontAwesome 字体资源
2014/06/22 PHP
php中Socket创建与监听实现方法
2015/01/05 PHP
ThinkPHP3.2.2实现持久登录(记住我)功能的方法
2016/05/16 PHP
php使用PDO执行SQL语句的方法分析
2017/02/16 PHP
js怎么覆盖原有方法实现重写
2014/09/04 Javascript
用JavaScript实现用一个DIV来包装文本元素节点
2014/09/09 Javascript
jquery Validation表单验证使用详解
2020/09/12 Javascript
jQuery中 attr() 方法使用小结
2015/05/03 Javascript
JS+CSS实现的日本门户网站经典选项卡导航效果
2015/09/27 Javascript
js文字横向滚动特效
2015/11/11 Javascript
javascript实现Email邮件显示与删除功能
2015/11/21 Javascript
全面解析多种Bootstrap图片轮播效果
2016/05/27 Javascript
Nodejs从有门道无门菜鸟起飞必看教程
2016/07/20 NodeJs
深入浅析JS Function()构造函数
2016/08/22 Javascript
vuejs实现ready函数加载完之后执行某个函数的方法
2018/08/31 Javascript
浅谈JS中几种轻松处理'this'指向方式
2019/09/16 Javascript
Postman如何实现参数化执行及断言处理
2020/07/28 Javascript
python socket网络编程步骤详解(socket套接字使用)
2013/12/06 Python
正确理解python中的关键字“with”与上下文管理器
2017/04/21 Python
python3 读取Excel表格中的数据
2018/10/16 Python
对python3新增的byte类型详解
2018/12/04 Python
Python利用scapy实现ARP欺骗的方法
2019/07/23 Python
Python使用循环神经网络解决文本分类问题的方法详解
2020/01/16 Python
解决Tensorflow 使用时cpu编译不支持警告的问题
2020/02/03 Python
如何基于Python pygame实现动画跑马灯
2020/11/18 Python
实习自我评价怎么写
2013/12/02 职场文书
安全标准化汇报材料
2014/02/03 职场文书
会计核算科岗位职责
2014/03/19 职场文书
小学生交通安全寄语
2015/02/27 职场文书
企业管理不到位检讨书
2019/06/27 职场文书
七年级作文之我的梦想
2019/10/16 职场文书
基于JavaScript实现省市联动效果
2021/06/22 Javascript
vue中data里面的数据相互使用方式
2022/06/05 Vue.js