Android組件化開發(fā)之SPI

Java SPI全稱Service Provider Interface撬呢,是Java提供的一套用來被第三方實(shí)現(xiàn)或者擴(kuò)展的API玷禽,它可以用來啟用框架擴(kuò)展和替換組件鞍历。實(shí)際上是“基于接口的編程+策略模式+配置文件”組合實(shí)現(xiàn)的動態(tài)加載機(jī)制.

ServiceLoader的使用

操作步驟:

1、定義一個(gè)接口文件

2背蟆、寫出多個(gè)該接口文件的實(shí)現(xiàn)

3鉴分、在 src/main/resources/ 下建立 /META-INF/services 目錄, 新增一個(gè)以接口命名的文件 , 內(nèi)容是要接口的實(shí)現(xiàn)類全路徑

4带膀、使用ServiceLoader類 來獲取到這些實(shí)現(xiàn)的接口

先創(chuàng)建一個(gè)interface的module志珍。

1631428120(1).png

然后在其他的模塊實(shí)現(xiàn)這個(gè)接口,并在實(shí)現(xiàn)這個(gè)接口的module中創(chuàng)建一個(gè)resources文件夾垛叨,文件夾里建一個(gè)文件碴裙,文件名為(對應(yīng)接口的全路徑 + 接口名),文件里面寫的內(nèi)容則為其(實(shí)現(xiàn)類的全路徑+實(shí)現(xiàn)類名)点额。在操作過程中舔株,遇到了一個(gè)坑,就是文件夾是兩級文件夾还棱,我在操作的時(shí)候圖簡單载慈,直接META-INF.services,結(jié)果導(dǎo)致通過ServiceLoader獲取實(shí)現(xiàn)類的時(shí)候,獲取為空珍手。這里應(yīng)該先創(chuàng)建一個(gè)文件夾办铡,命名為META-INF辞做,然后再在這個(gè)文件夾再創(chuàng)建一個(gè)文件夾,命名為services寡具,雖然在AS上顯示仍然為META-INF.services秤茅,但是這是一個(gè)二級文件夾 ,而我那種做法只算以及文件夾童叠。導(dǎo)致獲取不到文件里的內(nèi)容框喳。

1631428877(1).png

然后創(chuàng)建一個(gè)help類,其具體的實(shí)現(xiàn)為:


public class ServiceHelper {
    //針對一種接口多個(gè)實(shí)現(xiàn)類操作
    public static <T> List<T> getServices(Class<T> interfaceClass){
        ServiceLoader loader = ServiceLoader.load(interfaceClass);
        Iterator iterator = loader.iterator();
        List<T> list = new ArrayList<>();
        while (iterator.hasNext()){
            T t = (T) iterator.next();
            if (t != null){
                list.add(t);
            }
        }
        return list;
    }

    //針對一個(gè)接口一個(gè)實(shí)現(xiàn)類操作
    public static <T> T getService(Class<T> interfaceClass){
        ServiceLoader loader = ServiceLoader.load(interfaceClass);
        Iterator<T> iterator = loader.iterator();
        if (iterator.hasNext()){
            return (T) iterator.next();
        }else {
            return null;
        }
    }
}

然后在App模塊中調(diào)用厦坛,

AInterface aInterface =  ServiceHelper.getService(AInterface.class);
Log.e("zzf",aInterface + "");
BInterface bInterface = ServiceHelper.getService(BInterface.class);
Log.e("zzf",aInterface.getname() +"------------" + bInterface.getname());

1631340692(1).png
1631341048(1).png

這種方法在平常組件化開發(fā)中非常便利五垮,但是每次都需要到/META-INF/services 目錄建立文件,不能動態(tài)添加杜秸。因此采用Google的@AutoService放仗,他可以幫我們在編譯的時(shí)候動態(tài)去生成這些東西。

ServiceLoader + @AutoService的使用

添加依賴:

implementation 'com.google.auto.service:auto-service:1.0'
annotationProcessor 'com.google.auto.service:auto-service:1.0'

接口module不需要變撬碟,我們只需要在實(shí)現(xiàn)類進(jìn)行改變一下即可:

@AutoService(CInterface.class)
public class C2Impl implements CInterface {
    @Override
    public String getName() {
        return "C2Impl";
    }
}

只需要在具體的實(shí)現(xiàn)類上面加上一個(gè)@AutoService注解诞挨,參數(shù)則為接口的class類。

然后在App模塊中調(diào)用呢蛤,

List<CInterface> list = ServiceHelper.getServices(CInterface.class);
for (CInterface cInterface:list){
    Log.e("zzf",cInterface.getName());
}
ARouter

阿里的ARouter框架就是是借助了這種思想亭姥,它只需要我們的自己的接口繼承IProvider接口,

public interface BInterface extends IProvider {
    String getname();
}

然后在B模塊實(shí)現(xiàn)接口

@Route(path = "/user/BInterface")
public BImpl implements BInterface{
    @Override
    public String getname() {
        return "A2Impl";
    }
}

然后在其他模塊通過ARouter注解獲取實(shí)例

@Autowired//(name = "/user/BInterface")
    BImpl mBImpl;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ARouter.getInstance().inject(this);
        ...
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末顾稀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子坝撑,更是在濱河造成了極大的恐慌静秆,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巡李,死亡現(xiàn)場離奇詭異抚笔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)侨拦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門殊橙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狱从,你說我怎么就攤上這事膨蛮。” “怎么了季研?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵敞葛,是天一觀的道長。 經(jīng)常有香客問我与涡,道長惹谐,這世上最難降的妖魔是什么持偏? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮氨肌,結(jié)果婚禮上鸿秆,老公的妹妹穿的比我還像新娘。我一直安慰自己怎囚,他們只是感情好卿叽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著桩了,像睡著了一般附帽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上井誉,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天蕉扮,我揣著相機(jī)與錄音,去河邊找鬼颗圣。 笑死喳钟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的在岂。 我是一名探鬼主播奔则,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蔽午!你這毒婦竟也來了易茬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤及老,失蹤者是張志新(化名)和其女友劉穎抽莱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骄恶,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡食铐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了僧鲁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虐呻。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖寞秃,靈堂內(nèi)的尸體忽然破棺而出斟叼,到底是詐尸還是另有隱情,我是刑警寧澤春寿,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布犁柜,位于F島的核電站,受9級特大地震影響堂淡,放射性物質(zhì)發(fā)生泄漏馋缅。R本人自食惡果不足惜扒腕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望萤悴。 院中可真熱鬧瘾腰,春花似錦、人聲如沸覆履。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽硝全。三九已至栖雾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伟众,已是汗流浹背析藕。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凳厢,地道東北人账胧。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像先紫,于是被迫代替她去往敵國和親治泥。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353