CC框架實(shí)踐(2):Fragment和View的組件化

前言

本文將介紹如何在CC框架下實(shí)現(xiàn)Fragment和View的組件化。

一、需求背景

在android組件化過程中,你有沒有遇到這樣的問題:

  • 單Activity + 多Fragment的架構(gòu)下,如何進(jìn)行Fragment的組件化?
  • 主界面上的Fragment太多,想用組件化進(jìn)行管理,該怎么做?
  • 一個(gè)功能模塊比較獨(dú)立,但在主界面使用了其中一個(gè)Fragment,如何解耦?
  • 對(duì)某些View進(jìn)行了封裝或者自定義的View,功能比較獨(dú)立,是作為基礎(chǔ)庫通過類依賴使用好還是作為組件使用比較好?如果要作為組件使用,那要如何組件化?

二、現(xiàn)有的一些解決方案:

  • 在主app中依賴所有組件,所以在主app中可直接使用這些組件中的Fragment或View的類
    • 直接使用具體的類將產(chǎn)生耦合,違背了組件化的解耦目的
    • 組件之間的fragment引用也需要直接依賴,這樣就變成了一個(gè)庫而非組件
  • 使用ARouter來獲取Fragment對(duì)象來實(shí)現(xiàn)Fragment組件化
    • 由于沒有Fragment的具體類型,只能調(diào)用到系統(tǒng)中Fragment的public方法,不能進(jìn)行業(yè)務(wù)通信
    • 由于View的創(chuàng)建需要用到Activity對(duì)象(用Application對(duì)象會(huì)導(dǎo)致Activity設(shè)置的Theme樣式失效),無法通過這種方式來獲取
  • 創(chuàng)建一個(gè)公共庫,供所有組件依賴,所有組件在初始化時(shí),將組件內(nèi)的Fragment和View注冊(cè)到公共庫中生成一個(gè)映射表。組件通過調(diào)用公共庫的映射表查找對(duì)應(yīng)的Fragment或View的類
    • 跟用ARouter獲取Fragment一樣,在組件中無具體類型時(shí)無法進(jìn)行業(yè)務(wù)通信
    • 如果要用于獲取View,其構(gòu)造方法的參數(shù)列表調(diào)用方需要了解,在一定程度上也屬于類耦合
  • 使用ARouter的獲取Service方式實(shí)現(xiàn),對(duì)外暴露服務(wù),在公共庫中定義接口,提供創(chuàng)建、業(yè)務(wù)通信相關(guān)的方法,在組件中實(shí)現(xiàn)此接口的具體功能,調(diào)用方通過動(dòng)態(tài)獲取接口實(shí)現(xiàn)類來調(diào)用業(yè)務(wù)功能。這種方式能實(shí)現(xiàn)Fragment和View的組件化調(diào)用和業(yè)務(wù)通信,實(shí)現(xiàn)的也比較優(yōu)雅,但接口的管理成本有點(diǎn)高。
    • 接口放在公共庫中,一般用以下2種方式實(shí)現(xiàn):
      • 為每個(gè)向外提供Fragment或View的組件額外創(chuàng)建一個(gè)公共庫,供需要調(diào)用的組件依賴(感覺好麻煩,還不如直接依賴組件...)
      • 所有組件的這些接口統(tǒng)一放在一個(gè)公共庫中,供所有組件依賴。但這個(gè)庫的維護(hù)成本就比較高了,每次有新的接口或者原接口新增/修改方法都要修改這個(gè)庫。

三、先簡單介紹一下CC框架

CC: Component Caller(github地址),是一個(gè)可跨app進(jìn)行組件調(diào)用的android組件化開發(fā)框架,可支持包括Activity跳轉(zhuǎn)、數(shù)據(jù)獲取、網(wǎng)絡(luò)請(qǐng)求等等幾乎所有指令的跨組件調(diào)用。

組件實(shí)現(xiàn)方可自行決定是同步實(shí)現(xiàn)還是異步實(shí)現(xiàn)。

調(diào)用方可自行決定是同步調(diào)用還是異步調(diào)用(<font color=red>Notice: 不要在主線程同步調(diào)用耗時(shí)操作</font>)。

并且組件調(diào)用可關(guān)聯(lián)Activity和Fragment的生命周期(在onDestroy被調(diào)用時(shí)自動(dòng)取消調(diào)用,避免出現(xiàn)內(nèi)存泄露)

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

CC框架的實(shí)現(xiàn)原理 詳細(xì)介紹

四、在CC框架中如何實(shí)現(xiàn)Fragment的組件化?

CC的參數(shù)和回調(diào)結(jié)果使用的數(shù)據(jù)結(jié)構(gòu)是Map,在app內(nèi)部可以傳遞任何類型。

  1. 通過CC調(diào)用獲取組件中的Fragment對(duì)象

    1.1 組件調(diào)用方按如下方式調(diào)用,并從回調(diào)結(jié)果中獲取Fragment,例如:

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

    1.2 組件實(shí)現(xiàn)方按如下方式設(shè)置結(jié)果,例如:

    CC.sendCCResult(cc.getCallId(), CCResult.success("key", new MyFragment()));
    
  2. 與Fragment進(jìn)行通信

    組件化實(shí)施的主要目的之一是業(yè)務(wù)隔離:<b>只暴露調(diào)用協(xié)議給外部</b>(類似于app端與服務(wù)端的通信接口),內(nèi)部實(shí)現(xiàn)的更改對(duì)外部無影響。甚至組件的插拔和替換都不影響調(diào)用方(只要組件調(diào)用方做好組件調(diào)用失敗的降級(jí)處理,例如1.1示例代碼中的if (fragment != null) {...}。)

    所以,F(xiàn)ragment中的具體業(yè)務(wù)邏輯應(yīng)由組件自身內(nèi)部來實(shí)現(xiàn),在組件調(diào)用方(如:Activity)中通過CC調(diào)用組件暴露的接口來完成。

    2.1 組件調(diào)用方將fragment對(duì)象及其它參數(shù)通過CC傳遞給組件,例如:

    boolean success = CC.obtainBuilder("ComponentName")
        .setActionName("updateTextView") //action名稱
        .addParam("fragment", fragment) //目標(biāo)fragment對(duì)象
        .addParam("value", text) //設(shè)置參數(shù)
        .build().call().isSuccess();
    

    2.2 組件中接收fragment對(duì)象及其它參數(shù),并調(diào)用fragment對(duì)象的指定方法實(shí)現(xiàn)對(duì)應(yīng)的業(yè)務(wù),例如:

    @Override
    public boolean onCall(CC cc) {
        String actionName = cc.getActionName();
        if ("updateTextView".equals(actionName)) {
            MyFragment fragment = cc.getParamItem("fragment");//接收fragment對(duì)象
            if (fragment != null) {
                String text = cc.getParamItem("value", "");//接收其它參數(shù)
                fragment.updateText(text);//調(diào)用fragment的方法
                CC.sendCCResult(cc.getCallId(), CCResult.success());//回調(diào)結(jié)果
            } else {
                //回調(diào)錯(cuò)誤信息
                CC.sendCCResult(cc.getCallId(), CCResult.error("no fragment params"));
            }
        }
        return false;
    }
    

五、 View有沒有必要組件化?

答案是:對(duì)于一些封裝過的View、自定義View(特別是第三方自定義View)是有必要的。

理由是:組件化能很好的解耦,將業(yè)務(wù)實(shí)現(xiàn)完全交給組件內(nèi)部完成,只要接口協(xié)議不發(fā)生變化,實(shí)現(xiàn)方式發(fā)生改變時(shí)不會(huì)影響到使用方式。

網(wǎng)上很多組件化方案中,都是將自定義View(自己寫的或者第三方庫)作為公共庫來使用。如果沒有做個(gè)適配層(Adapter)而直接使用自定義View的類,將會(huì)導(dǎo)致View的耦合度很高,降低系統(tǒng)的擴(kuò)展性。

六、在CC框架中如何實(shí)現(xiàn)View的組件化?

與Fragment組件化一樣,通過CC獲取對(duì)象和業(yè)務(wù)調(diào)用。

唯一的差別是:在獲取View對(duì)象時(shí)需要將Activity對(duì)象傳給組件

View view = CC.obtainBuilder("ComponentName")
        .setContext(activity) //將activity對(duì)象傳給組件,用于View的初始化
        .build().call().getDataItem("key");
if (view != null) {
    //add view to container
}

總結(jié)

關(guān)于android的組件化文章一般都只是介紹如何進(jìn)行Activity的跳轉(zhuǎn)及服務(wù)調(diào)用,對(duì)于Fragment的組件化一直沒有很好的解決,View的組件化幾乎沒有被提到。

本文介紹了在CC組件化框架下實(shí)現(xiàn)Fragment及View組件化的方式,為android工程組件化的道路掃除一個(gè)障礙。

系列文章

CC框架實(shí)踐(1):實(shí)現(xiàn)登錄成功再進(jìn)入目標(biāo)界面功能

CC框架實(shí)踐(2):Fragment和View的組件化

CC框架實(shí)踐(3):讓jsBridge更優(yōu)雅

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,765評(píng)論 25 709
  • tags:胡謅八扯 女人有了孩子之后開始多了憂慮,我老婆也不例外。聽說幾個(gè)朋友為孩子報(bào)了各種班,于是也在各種謀劃,...
    MarkNote閱讀 658評(píng)論 6 4
  • 天好灰 小鳥都走了 我拿著一支竹竿 想要?jiǎng)冮_厚厚的天 我用力 使勁 我放棄 顫抖 我剝不開厚厚的天 就像小鳥永遠(yuǎn)都...
    雷小佳Adele閱讀 180評(píng)論 0 0
  • 體質(zhì):是人的生命過程中,在先天稟賦和后天獲得的基礎(chǔ)上,逐漸形成的在形態(tài)結(jié)構(gòu)、生理功能、物質(zhì)代謝和性格心理方面,綜合...
    餅干_7c28閱讀 428評(píng)論 0 1
  • 今天聊一下游戲界的世界最早。 世界上最早的家用電子游戲 世界上最早的家用電子游戲是PONG,被譯為雅達(dá)利乓。 19...
    天芒云閱讀 946評(píng)論 0 0

友情鏈接更多精彩內(nèi)容