【Android】api與implementation的區別

一、從3.4版本的gradle開始,compile已經被api與implementation取代,官網也給出了三者之間的區別:

從官網介紹可以看出,implementation可以讓module在編譯時隱藏自己使用的依賴,但是在運行時這個依賴對所有模塊是可見的。而api與compile一樣,無法隱藏自己使用的依賴。
具體通過例子來看,下圖爲項目結構:

app依賴模塊mylibrary1、mylibrary1依賴模塊mylibrary3
mylibrary1如下:

package com.example.mylibrary1;
/**
 * @author heshufan
 * @date 2018/8/9.
 */
public class MyClass1 {
    public static String  get(){
        return "MyClass1";
    }
}

mylibrary3如下:

package com.example.mylibrary3;
/**
 * @author heshufan
 * @date 2018/8/13.
 */
public class MyClass3 {
    public static String get(){
        return "MyClass33";
    }
}

當mylibrary1 使用api依賴mylibrary3時,

api project(':mylibrary3')

在App中可以直接調用MyClass3類,也就是依賴可以傳遞。

package com.example.heshufan.learnapiandimp;
import com.example.mylibrary1.MyClass1;
import com.example.mylibrary3.MyClass3;
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyClass1.get0();
        MyClass3.get();
    }
}

當mylibrary1使用implemention依賴mylibrary3時,

implementation project(':mylibrary3')

在App中,無法直接調用mylibrary3

從上面的例子可以看出,在多module中,implementation確實可以起到隱藏依賴的作用,網上很多的文章都只講到了這點,那麼這樣做的目的是什麼呢?其實這並不是Google設計implemention與api的目的,因爲官方文檔中說這樣設計的目的在於減少build的時間,那麼implemention是如何減少build time的呢?

二、我們再新建一個module:mylibrary4,現在的項目結構如圖:

那麼現在的項目層級如下圖所示:

1、如果mylibrary3使用api依賴mylibrary4,那麼當mylibrary4發生變化時,編譯需要重新編譯mylibrary4、mylibrary3、mylibrary1;
2、如果mylibrary3使用implemention依賴mylibrary4,那麼當mylibrary4發生變化時,編譯需要重新編譯mylibrary4、mylibrary3,這個時候不需要編譯mylibrary1,這樣就可以節約build time;

爲此我驗證了兩種依賴下項目的build time,每次重新編譯前clean project,改變mylibrary4,然後rebuild project,再查看build time。

使用implemention的build time:

使用api的build time

可以看到api的build time比implemention多了1秒多,多次運行都多了1秒多,這還是在module比較小的情況下。如果包比較多,比較大,那麼可以節約的時間是非常可觀的。
總結起來:如果api依賴,一個module發生變化,這條依賴鏈上所有的module都需要重新編譯;而implemention,只有直接依賴這個module需要重新編譯。

三、現在在回過頭來看一下依賴傳遞的問題,之前驗證了使用implemention,app不能拿到MyClass3,這是在本地依賴的情況下,而現在的模塊化開發多采用遠程依賴的模式進行合作。那麼如果採用maven遠程依賴呢?
同樣採用之前的例子,我們新建一個module :mylibrary2

我們將其上傳到我們的本地maven

最後在mylibrary1中利用implemention依賴mylibrary2

    //mylibrary1
    implementation 'com.example:mylib:1.0.3'

然後我們再將mylibrary1上傳到本地maven,然後在app中遠程依賴mylibrary1

    //mylibrary2
    implementation 'com.example:myClass2:1.0.0'

也就是app遠程implementation mylibrary1,mylibrary1遠程implemention mylibrary2,這時候app就可以直接拉到mylibrary2中的myClass2類(命名不規範,別學我)

而如果app本地implementation mylibrary1,mylibrary1遠程implemention mylibrary2,這時候app則不能獲取到mylibrary2中的myClass2類,依然起到了依賴隔離的作用。

由以上可以看到在全部遠程依賴模式下,無論是api還是implemention都起不到依賴隔離的作用。不過,在遠程依賴模式下,依賴的一個模塊如果版本發生變化,implemention與api的構建速度誰快誰慢還需要進一步研究。

綜上,在多層次模塊化(大於等於三層module)開發時,如果都是本地依賴,implementation相比api,主要優勢在於減少build time。如果只有兩層module,api與implemention在build time上並無太大的差別。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章