【Android翻译】组件通信模式

目标:避免紧耦合

本文对原文进行了精简

原文链接:Communication patterns for application components

紧耦合

组件之间相互持有引用,以及直接调用方法.在下面的代码中,MenuFragment持有MagazineActivity的直接引用,因此, MenuFragment 就与 MagazineActivity紧耦合了.
一旦没有了MagazineActivity,就无法工作了.

// 紧耦合示例

class MenuFragment extends Fragment {
    private void onArticleClick(int articleId) {
        MagazineActivity magAct = (MagazineActivity) getActivity();
        magAct.showArticle(articleId);
    }
}

在这样的设计中,一个类的修改可能会影响到一大波相关的类,如果开发中还涉及到多个开发人员,那么这种情况带来的只会是痛苦和悲哀..

松耦合的核心就是一种减少组件之间的依赖关系,一个松耦合系统可以很方便的分解为良构的元素.这样就使得系统更具有弹性与扩展性.
每个开发人员可以维护一个单独的模块,并使用标准的协议与其他部分通信.

常规解耦方式:接口

(个人补充:接口并不是单纯指代的java里面的interface关键字,而是指的一种消息规范/协议)
接口是一个强大的解耦工具:类可以通过接口进行通信,而不必要直接引用另一个具体类.一个类可以向外提供一个接口供其他类与之通信.在这个抽象层上,其他类不用关心具体的实现是什么.

//接口示例

class MenuFragment extends Fragment {
    public static MenuFragment instantiate(ArticleSwitcher articleSwitcher) {
        MenuFragment menuFragment = new MenuFragment();
        menuFragment.articleSwitcher = articleSwitcher;
        return menuFragment;
    }

    ArticleSwitcher articleSwitcher;

    public void onArticleClick(int articleId) {
        articleSwitcher.showArticle(articleId);
    }
}

使用接口的缺点:

  1. 组件之间还是需要相互了解以传递接口,部分依赖依旧存在
  2. 接口不能通过intent传递
  3. 在大项目中,接口数量会急剧增加,导致大量的模板代码
  4. 当接口在组件之间传递时会形成接口链,导致复杂度上升

优雅解决方案:消息总线

基于发布/订阅者模式的通信方案.发布者发布一个通知,订阅者得到通知并做出反应,因此,发布者和订阅者之间就实现了解耦.

实现消息总线

隐式intent + BroadcastReceiver

通过隐式Intent的通信可以看作是消息队列的一种形式:
sendBroadcast(Intent) 或者 startActivity(Intent)是发布者方法,含有相应IntentFilter的BroadcastReceiver 或者 Activity则扮演订阅者的角色.

优点与缺点

优点:可以跨应用传递,也是Android里面的标准方法

缺点:无法传递复杂数据,必须通过bundle来传递

FluffyEvents 就是一个通过 BroadcastReceiver 实现的消息总线.

EventBus: 基于事件的消息总线

(“事件"本身也是一种消息,原理还是订阅/发布者模式)

事件本身可以是任何java类,如下:

// 一个示例事件类

class DownloadProgressEvent {
    private float progress;
    public DownloadProgressEvent(float progress) {
        this.progress = progress;
    }

    public float getProgress() {
        return progress;
    }
}
EventBus: 大致原理

EventBus使用合适的数据结构来维持事件以及订阅者的对应关系,比如Otto使用的方式:

/** Cache event bus subscriber methods for each class. */
private static final Map<Class<?>, Map<EventClass, Set>> SUBSCRIBERS_CACHE = new HashMap<Class<?>, Map<EventClass, Set>>();

每当有订阅者注册或者注销的时候,都会同时更新相应的对应关系,通常,Activity 或者 Fragment会在onResume阶段进行注册,在onPause阶段进行注销.(译者注:可以减少内存泄露的问题)

每当有事件发布的时候,EventBus遍历整个对应关系,找到所有符合条件的订阅者方法并执行.

Sticky Event

类似Android原生的StickyBroadcast,使得一个订阅者在任何时候注册都可以获得这个事件.

总结

由于EventBus并不是Android的内在机制,因此无法跨应用传递事件.

比较常用的两个EventBus开源类库:

Square’s Otto:基于注解,在Guava EventBus基础上针对Android平台进行了优化

GreenRobot’s EventBus:更好的线程分发机制.

(译者注: EventBus比较适合组件之间的解耦, 而接口是一个更抽象的概念,还可以用在view或者其他方面)

Android分享 Q群:315658668

时间: 2024-10-15 12:49:41

【Android翻译】组件通信模式的相关文章

Vue组件通信模式

概述 在Vue.js中,有几种我们能用的内部组件通信的方法.一般的属性和事件对于大多数场景来说已经够用了,但是除此之外,还有其他可用的方法. 属性和事件 当然,一般的通信方法用到了属性和事件.这种常用的模式是组件中一种强大的通信方式,它不用在相关的组件上引入任何依赖和限制. 属性 属性允许你传递任意的数据类型到一个子组件中,并且允许你控制组件接收何种类型的数据.属性的更新也是响应式的,这使得无论任何时候,父组件的数据改变,子组件就会更新. 模板用法: 123 <my-component v-bi

Android 四大组件 与 MVC 架构模式

作为一个刚从JAVA转过来的Android程序员总会思考android MVC是什么样的? 首先,我们必须得说Android追寻着MVC架构,那就得先说一下MVC是个啥东西! 总体而来说MVC不能说是一个设计模式,因为划分维度太大,所以MVC应该属于架构模式! 百度百科 —— MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑和数据显示分离的方法组织代码,将业务逻辑被聚集到一个部件

Android组件通信(章节摘要)

1,不同的Activity之间的跳转可以使用Intent完成,用户也可以通过onActivityResult()方法来接收Activity返回的结果. 2,在Android操作系统中,提供了多个可以操作的Intent,用户只需要设置好要跳转的Action以及附加的若干数据即可实现这些程序的调用. 3,Activity的生命周期包括运行态(Running State),暂停态(Pauserd State)和停止态(Stopped State). 4,使用ActivityGroup要比使用TabHo

Android四大组件之BroadcastReceiver详细解析

什么是BroadcastReceiver? BroadcastReceiver作为Android四大组件之一,在实际开发中也发挥着重要的作用,广播机制在Android程序通信中至关重要,广播其实与我们现实生活中的电台很相似,电台在某个频道上发送它的内容,那么只要有在收听这个频道的人都会收到这些内容.在Android中,广播也同样分为两个角色:广播发送者.广播接收者. BroadcastReceiver的应用场景 1.在一个应用中,我们的Activity与Service的通信就需要用到广播来作为中

App 组件化/模块化之路——Android 框架组件(Android Architecture Components)使用指南

面对越来越复杂的 App 需求,Google 官方发布了Android 框架组件库(Android Architecture Components ).为开发者更好的开发 App 提供了非常好的样本.这个框架里的组件是配合 Android 组件生命周期的,所以它能够很好的规避组件生命周期管理的问题.今天我们就来看看这个库的使用. 通用的框架准则 官方建议在架构 App 的时候遵循以下两个准则: 关注分离 其中早期开发 App 最常见的做法是在 Activity 或者 Fragment 中写了大量

Android之Http通信——1.初识Http协议

Android之Http通信--1.初识Http协议 引言: 今天是六一儿童节,先在这里给各位超龄儿童说声节日快乐哈~( ╯□╰ ),小猪也象征性地给群里的小朋友们派了红包-嗯,忙碌的五月最终过去了,做毕设,写论文,拍毕业照,答辩,辞职.各种各样的事,也算忙完了,好吧.小猪如今又在一家新的公司上班了.第三间公司了.你们肯定会认为小猪三心二意是吧,毕竟才差点儿相同毕业就换了那么多家公司,然后可能问我."小猪你什么时候跳第四间公司",哈哈,应该不会了哈,怎么说呢,事实上我还是非常专一的,毕

Android业务组件化之子模块SubModule的拆分以及它们之间的路由Router实现

前言: 前面分析了APP的现状以及业务组件化的一些探讨(Android业务组件化之现状分析与探讨),以及通信的桥梁Schema的使用(Android业务组件化之URL Schema使用),今天重点来聊下子模块SubModule的拆分以及它们之间的路由Router实现.本篇涉及的相关知识比较多,阅读本篇之间需要大致了解一下Java的注解(Java学习之注解Annotation实现原理).Java的动态代理机制(Java设计模式之代理模式(Proxy))等.业务组件化是一个循序渐进的过程,一开始很难

Android UI组件之EditText 实现网站注册效果的校验

时间过得太快,还没有什么感觉就到周末了,人生五十载,如梦亦如幻.不过我还没那么老.前两天曾说过,如果需要实现输入IP的功能,那么我们可以整一个自定义控件,然后对他进行事件监听,巴拉巴拉一大堆,好不容易做完了.后来想想,这是为了符合我们平常在PC上的习惯而去自定义的.那么如果只是单纯的为了输入一个IP地址,然后得到结果,不想去这么折腾,有没有什么好办法呢? 很显然是有的,那就今天就来看看Android最常用的组件之一的EditText,虽然之前用的也是EditText,但是侧重点其实是自定义控件,

Android自定义组件系列【5】——进阶实践(1)

简介 项目开发中发现问题.解决问题这个过程中会出现很多问题,比如重复出现.某个问题的遗留,这些问题的本质就是设计模式.今天记录设计模式的知识点. 内容 在java以及其他的面向对象设计模式中,类与类之间主要有6种关系,他们分别是:依赖.关联.聚合.组合.继承.实现.它们的耦合度依次增强. 依赖关系:对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系.关联关系:分为单向关联和双向关联.在java中,单向关联表现为:类A当中使用了