本文正在参与「金石计划 . 分割6万现金大奖」

前言

因为之前被问到过,最近突然有点爱好上头,所以想简略做一个总结,现在开发根本都会用到组件化,那么咱们有没有想过在不运用别人写的框架的情况下,自己怎样去完成组件化。

本次主要讲两个互不依靠的组件之间的通讯,而假如两个组件之间存在依靠,那就能够直接去调用,这种情况就不说了。本次主要讲的是技能层面的完成,不讲架构层面的,因为这个功用假如要做架构规划,那将会是一个大工程,关于组件间的架构规划,很多大佬也有讲。可是详细的技能完成,却很少有人提到,我这儿就简略做个总结。

组件间控件的跳转

比如说组件A的一个Activity跳转到组件B的一个Activity,详细是怎样完成的。

这儿咱们能够用ARouter来剖析,我之前也有一篇文章简略写过,感爱好的能够去看看/post/714936…

这儿就直接给出结论:显式跳转

简略来说便是组件A拿到组件B的Class之后进行显现跳转。

Android组件通信方式

资源调用

资源调用就更简略了,尽管在不同的模块, 可是AssetManager会统一加载路径,所以直接用Resource就能加载资源了。

组件通讯

这个才是我这次要讲的重点,举个栗子,互不依靠的模块A调用模块B的一个办法,怎样去调用?

其实提到这个,很多人第一反响便是EventBus,那除了EventBus,还有其它的能完成这个功用的办法吗?他们究竟是怎样完成的?

反射

让咱们请出今天的一号选手,反射

反射选手驰骋Android界可谓是无所不能,假如时刻回到很早很早以前,没有ARouter,没有各种Bus,你让我来做,我或许第一个想到的便是反射。

Android组件通信方式

反射能够完成这两个模块不引证相同模块的情况下,能让其间一个模块调用另一个模块的办法、特点等。

只要能拿到Class目标,你就能够做到任何你想做的事,这儿咱们的组件同属一个包的情况下,你能够经过类名等办法去获取到Class目标,哪怕是不同包,你也能够经过ClassLoader去拿到Class目标。

EventBus

让咱们请出二号选手EventBus,EventBus可谓是Android界的当红炸子鸡,它试用简略,只需要一个办法一个注释,便能快速的完成组件间的跳转。

可是它也有害处,假如你只会乱用EventBus的话,我信任接手你项目的那位老兄十分的想感谢你的全家。当项目变得越来越大的时分,功用变得越来越大的时分,漫天乱飞的EventBus会让开发者活着煎熬中。

接下来能够简略看看EventBus是怎样在组件间进行络绎的(我现在项目没用到这个,因为我这今天网慢,下不下来,我直接github上拿代码讲)。

直接看post,不用管细节,这儿不是源码解析EventBus,仅仅为了找中心,所以跟进主线使命

Android组件通信方式

Android组件通信方式

Android组件通信方式

Android组件通信方式

Android组件通信方式

简略瞟一眼,发现有关线程什么的,然后最终调到subscription.subscriberMethod.method.invoke(subscription.subscriber, event),我第一眼就感觉是用了反射,没关系,能够再进去详细看看。

Android组件通信方式

果然是反射,所以结论便是:EventBus是基于反射来完成组件间通讯
没想到这2号选手是1号选手的小弟。

ARouter

有请3号选手ARouter,嗯?不对,3号选手不是做跳转用的吗?当然不是,ARouter同样是能够完成组件通讯的,可不仅仅能做Activity跳转。

咱们能够看看Warehouse,它还有provider和interceptor

class Warehouse {
    // Cache route and metas
    static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
    static Map<String, RouteMeta> routes = new HashMap<>();
    // Cache provider
    static Map<Class, IProvider> providers = new HashMap<>();
    static Map<String, RouteMeta> providersIndex = new HashMap<>();
    // Cache interceptor
    static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
    static List<IInterceptor> interceptors = new ArrayList<>();
    static void clear() {
        routes.clear();
        groupsIndex.clear();
        providers.clear();
        providersIndex.clear();
        interceptors.clear();
        interceptorsIndex.clear();
    }
}

咱们主要是讲组件通讯,这儿就不源码解析ARouter了。

那一般ARouter怎样完成呢,其实ARouter内部有个IProvider,咱们能够写一个接口承继IProvider,这个就相当于一个服务的意思,咱们给这个组件写一个或多个服务,然后将服务提供给其它组件去调用,服务里边完成自己想要完成的功用。

Android组件通信方式

Android组件通信方式

然后ARouter有一部分操作便是经典的添加到路由表的操作,这个我也不多说了,看到这儿的假如还不知道ARouter的路由表的操作的话,能够先去了解一下,假如想简略了解,能够看我之前写的这篇文章/post/714936… ,这儿仍是主要讲重点代码

Android组件通信方式

看到上面的代码,拿到Class,然后调用Class的newInstance,这儿便是反射创立一个目标。所以能够得出结论:ARouter完成组件间通讯的办法便是反射
好家伙,没想到3号选手也是1号选手的小弟。
有点不相同的是,navigation办法的返回值return (T) postcard.getProvider();能够看出,尽管它是用了反射,可是仍是会让一个模块拿到另一个模块的接口,而要拿到接口,除了两个模块有依靠关系的做法之外,还有一个做法便是两个模块都共同依靠一个模块,接口界说在那个模块里边。

那有人或许会想,用反射不都能够完成互不依靠的情况下通讯了吗,为什么还要这样做。其实这便是一个架构层面的规划,咱们这儿只讲技能完成层面的,就不详细去说。但你能够想想他和2号选手eventBus有什么不同,为什么当功用多时,当代码多时,eventBus或许会看起来觉得很乱,可是ARouter不会。

部分播送

4号选手部分播送LocalBroadcastManager,也能完成组件间的通讯,它不会也是1号选手反射的小弟吧?

来看看它的做法,首先要有个概念,部分播送,是不能和一般的播送相同做到进程间通讯的,其实,它是一个单例。

public void registerReceiver(@NonNull BroadcastReceiver receiver,
        @NonNull IntentFilter filter) {
    synchronized (mReceivers) {
        ReceiverRecord entry = new ReceiverRecord(filter, receiver);
        ArrayList<ReceiverRecord> filters = mReceivers.get(receiver);
        if (filters == null) {
            filters = new ArrayList<>(1);
            mReceivers.put(receiver, filters);
        }
        filters.add(entry);
        for (int i=0; i<filter.countActions(); i++) {
            String action = filter.getAction(i);
            ArrayList<ReceiverRecord> entries = mActions.get(action);
            if (entries == null) {
                entries = new ArrayList<ReceiverRecord>(1);
                mActions.put(action, entries);
            }
            entries.add(entry);
        }
    }
}

看到注册播送的做法,便是把播送放到一个HashMap里边
private final HashMap<BroadcastReceiver, ArrayList> mReceivers = new HashMap<>();
至于是什么HashMap,你能够先不用管,猎奇的话能够自己去剖析源码,它的源码也很简略,这儿只为了讲重点。再看看发送音讯的操作

Android组件通信方式

办法是sendBroadcast,太长了我就截取一部分,从中看得出,它是用了Handler。所以能够得出结论:部分播送完成组件间通讯的办法是Handler+数组+单例

Android组件通信方式

总结

这次主要从技能层面去查看一些完成组件间通讯的办法详细是怎样完成的,总共有4位选手:反射、EventBus、ARouter、部分播送。他们形成了正义的三打一,其实这说明完成组件间通讯的办法无外乎两种,反射和Handler。

反射作为Android中的万金油,这是类和类加载机制的表现。而Handler是Android进程内通讯的桥梁。这些组件哪怕互不依靠,也存在于同一个进程中,所以Handler对他们有用,假如在不同的进程,那当然就要用Binder了。

技能层面的完成,便是这两种办法,而架构层面去完成组件间的通讯,那办法就多了,也更为杂乱,尽管直接用反射、EventBus、ARouter都是用了反射,但他们在架构上的规划不同,最终完成的效果也十分的不同。

假如你还有什么其它组件间的通讯办法,能够留言告诉我,假如我感爱好的话,也会再去看看它内部是怎样去完成。