CC框架实践(2):Fragment和View的组件化

前言

本文将介绍如何在CC框架下实现Fragment和View的组件化。

一、需求背景

在android组件化过程中,你有没有遇到这样的问题:

  • 单Activity + 多Fragment的架构下,如何进行Fragment的组件化?
  • 主界面上的Fragment太多,想用组件化进行管理,该怎么做?
  • 一个功能模块比较独立,但在主界面使用了其中一个Fragment,如何解耦?
  • 对某些View进行了封装或者自定义的View,功能比较独立,是作为基础库通过类依赖使用好还是作为组件使用比较好?如果要作为组件使用,那要如何组件化?

二、现有的一些解决方案:

  • 在主app中依赖所有组件,所以在主app中可直接使用这些组件中的Fragment或View的类
    • 直接使用具体的类将产生耦合,违背了组件化的解耦目的
    • 组件之间的fragment引用也需要直接依赖,这样就变成了一个库而非组件
  • 使用ARouter来获取Fragment对象来实现Fragment组件化
    • 由于没有Fragment的具体类型,只能调用到系统中Fragment的public方法,不能进行业务通信
    • 由于View的创建需要用到Activity对象(用Application对象会导致Activity设置的Theme样式失效),无法通过这种方式来获取
  • 创建一个公共库,供所有组件依赖,所有组件在初始化时,将组件内的Fragment和View注册到公共库中生成一个映射表。组件通过调用公共库的映射表查找对应的Fragment或View的类
    • 跟用ARouter获取Fragment一样,在组件中无具体类型时无法进行业务通信
    • 如果要用于获取View,其构造方法的参数列表调用方需要了解,在一定程度上也属于类耦合
  • 使用ARouter的获取Service方式实现,对外暴露服务,在公共库中定义接口,提供创建、业务通信相关的方法,在组件中实现此接口的具体功能,调用方通过动态获取接口实现类来调用业务功能。这种方式能实现Fragment和View的组件化调用和业务通信,实现的也比较优雅,但接口的管理成本有点高。
    • 接口放在公共库中,一般用以下2种方式实现:
      • 为每个向外提供Fragment或View的组件额外创建一个公共库,供需要调用的组件依赖(感觉好麻烦,还不如直接依赖组件...)
      • 所有组件的这些接口统一放在一个公共库中,供所有组件依赖。但这个库的维护成本就比较高了,每次有新的接口或者原接口新增/修改方法都要修改这个库。

三、先简单介绍一下CC框架

CC: Component Caller(github地址),是一个可跨app进行组件调用的android组件化开发框架,可支持包括Activity跳转、数据获取、网络请求等等几乎所有指令的跨组件调用。

组件实现方可自行决定是同步实现还是异步实现。

调用方可自行决定是同步调用还是异步调用(<font color=red>Notice: 不要在主线程同步调用耗时操作</font>)。

并且组件调用可关联Activity和Fragment的生命周期(在onDestroy被调用时自动取消调用,避免出现内存泄露)

CC框架的使用方式,可查看github中的 README文档

CC框架的实现原理 详细介绍

四、在CC框架中如何实现Fragment的组件化?

CC的参数和回调结果使用的数据结构是Map,在app内部可以传递任何类型。

  1. 通过CC调用获取组件中的Fragment对象

    1.1 组件调用方按如下方式调用,并从回调结果中获取Fragment,例如:

    Fragment fragment = CC.obtainBuilder("ComponentName")
            .build().call().getDataItem("key");
    if (fragment != null) {
        //show fragment
    }
    

    1.2 组件实现方按如下方式设置结果,例如:

    CC.sendCCResult(cc.getCallId(), CCResult.success("key", new MyFragment()));
    
  2. 与Fragment进行通信

    组件化实施的主要目的之一是业务隔离:<b>只暴露调用协议给外部</b>(类似于app端与服务端的通信接口),内部实现的更改对外部无影响。甚至组件的插拔和替换都不影响调用方(只要组件调用方做好组件调用失败的降级处理,例如1.1示例代码中的if (fragment != null) {...}。)

    所以,Fragment中的具体业务逻辑应由组件自身内部来实现,在组件调用方(如:Activity)中通过CC调用组件暴露的接口来完成。

    2.1 组件调用方将fragment对象及其它参数通过CC传递给组件,例如:

    boolean success = CC.obtainBuilder("ComponentName")
        .setActionName("updateTextView") //action名称
        .addParam("fragment", fragment) //目标fragment对象
        .addParam("value", text) //设置参数
        .build().call().isSuccess();
    

    2.2 组件中接收fragment对象及其它参数,并调用fragment对象的指定方法实现对应的业务,例如:

    @Override
    public boolean onCall(CC cc) {
        String actionName = cc.getActionName();
        if ("updateTextView".equals(actionName)) {
            MyFragment fragment = cc.getParamItem("fragment");//接收fragment对象
            if (fragment != null) {
                String text = cc.getParamItem("value", "");//接收其它参数
                fragment.updateText(text);//调用fragment的方法
                CC.sendCCResult(cc.getCallId(), CCResult.success());//回调结果
            } else {
                //回调错误信息
                CC.sendCCResult(cc.getCallId(), CCResult.error("no fragment params"));
            }
        }
        return false;
    }
    

五、 View有没有必要组件化?

答案是:对于一些封装过的View、自定义View(特别是第三方自定义View)是有必要的。

理由是:组件化能很好的解耦,将业务实现完全交给组件内部完成,只要接口协议不发生变化,实现方式发生改变时不会影响到使用方式。

网上很多组件化方案中,都是将自定义View(自己写的或者第三方库)作为公共库来使用。如果没有做个适配层(Adapter)而直接使用自定义View的类,将会导致View的耦合度很高,降低系统的扩展性。

六、在CC框架中如何实现View的组件化?

与Fragment组件化一样,通过CC获取对象和业务调用。

唯一的差别是:在获取View对象时需要将Activity对象传给组件

View view = CC.obtainBuilder("ComponentName")
        .setContext(activity) //将activity对象传给组件,用于View的初始化
        .build().call().getDataItem("key");
if (view != null) {
    //add view to container
}

总结

关于android的组件化文章一般都只是介绍如何进行Activity的跳转及服务调用,对于Fragment的组件化一直没有很好的解决,View的组件化几乎没有被提到。

本文介绍了在CC组件化框架下实现Fragment及View组件化的方式,为android工程组件化的道路扫除一个障碍。

系列文章

CC框架实践(1):实现登录成功再进入目标界面功能

CC框架实践(2):Fragment和View的组件化

CC框架实践(3):让jsBridge更优雅

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,964评论 25 707
  • tags:胡诌八扯 女人有了孩子之后开始多了忧虑,我老婆也不例外。听说几个朋友为孩子报了各种班,于是也在各种谋划,...
    MarkNote阅读 608评论 6 4
  • 天好灰 小鸟都走了 我拿着一支竹竿 想要剥开厚厚的天 我用力 使劲 我放弃 颤抖 我剥不开厚厚的天 就像小鸟永远都...
    雷小佳Adele阅读 150评论 0 0
  • 体质:是人的生命过程中,在先天禀赋和后天获得的基础上,逐渐形成的在形态结构、生理功能、物质代谢和性格心理方面,综合...
    饼干_7c28阅读 366评论 0 1
  • 今天聊一下游戏界的世界最早。 世界上最早的家用电子游戏 世界上最早的家用电子游戏是PONG,被译为雅达利乓。 19...
    天芒云阅读 874评论 0 0