作為Android開發人員,IPC應該是我們能經常聽到的。但是什么是IPC?IPC的使用場景是什么?Android中IPC的實現模式有哪幾種?這些一連串的問題,也許對于初學者來說就不那么簡單了。接下來,讓我們一起去詳細了解一下這個常用但并不簡單的IPC機制。
??IPC是Inter-Process Communication 的簡稱,翻譯過來也就是我們經常提到的跨進程通信。要掌握跨進程通信,我們首先要了解什么是進程,而談到進程,線程也不可避免的需要了解,這里就放到一起介紹。從操作系統的層面來說,進程是CPU調度的最小的單元。而進程是指一個執行單元,在Android設備中,正常情況下一個進程就是一個應用。一個進程可以包含多個線程,所以說進程和線程的關系是包含和被包含的關系。
??什么情況下會出現多進程呢?通常情況下有以下兩種情況:第一種情況是單個應用因為某些原因自身需要采用多進程的模式,這個原因可能就比較多了,比如說有些模塊由于特殊的原因需要運行在單獨的進程中等。第二種情況就是兩個不同的應用之間需要進行數據的傳遞,此時就只能采用跨進程的方式去獲取所需的數據了。
Android中開啟多進程的方式
??在Android中如何開啟多進程呢,在Android中只有一種方法去開啟多進程,那就是在AndroidMenifest文件中給四大組件(Activity、Service、Receiver、ContentProvider)指定android:process屬性。下面舉例說明:
<activity
android:name=".Activity1"
android:process=":remote" />
<activity
android:name=".Activity2"
android:process="com.jyn.test.remote" />
??上面的代碼為Activity1和Activity2都指定了process屬性,并且二者的屬性值不同,這就意味著當前的應用又啟動了兩個新的進程。假設軟件的包名為com.jyn.test,當軟件運行后,系統會為Activity1創建一個單獨的進程,進程名為com.jyn.test:remote;為Activity2創建一個單獨的進程,進程名為com.jyn.test.remote.而沒有指定process的四大組件,則在默認進程中運行,默認進程名為包名(這里就是com.jyn.test)
??大家應該都注意到了Activity1 和Activity2的android:progress 屬性是有所區別的。Activity1的android:process 屬性以“:”開頭,而Activity2的則沒有,那具體的區別是什么呢:“:”的含義是指要在當前的進程名前面加上當前的包名,這是一種簡寫,所以Activity1完整的進程名是com.jyn.test:remote;對于Activity2中的聲明方式是一種完整的命名方式,不會附加包名信息。還有一點區別就是,以“:”開頭的進程屬于當前應用的私有進程,其他應用的組件不可以和它跑在同一個進程中,而進程名不以“:”開頭的進程屬于全局進程,其他應用是可以和它跑在同一個進程中(通過shareUID的方式)。
開啟多進程所引發的問題
從上面的內容中我們不難發現,開啟多進程的方法是比較簡單的,只需要給四大組件指定android:process屬性即可,但實際的開發工作中真的就是如此簡單嗎?如果直接說多線程的使用并不是如此簡單,我相信大多數人都不會信服。那我們還是實踐出真理,給一個實際的例子看看,我所說的不僅簡單到底體現在什么地方。
??新建兩個Activity:TestActivity和SecondActivity,然后我們再新建一個類Project,Project 中有一個public類型的靜態成員變量,具體代碼如下:
public class Project {
public static int SIZE = 1024;
}
??隨后在TestActivity的onCreate()方法中把SIZE值賦值為2048,在控制臺打印這個變量的值,然后啟動SecondActivity,在SecondActivity的onCreate()方法中也打印這個變量的值,輸出如下。
??由上圖可知,這個是正常的,因為靜態變量是可以在所有地方共享 的,在TestActivity中改變他的值后,在其他地方訪問就是改變后的結果了。
這時我們給SecondActivity添加android:process屬性,給SecondActivity重新開啟一個進程,看看結果會是怎樣的呢,經測試,結果如下所示:
11-08 10:09:12.986 15985-15985/com.jyn.test D/TestActivity: 2048
11-08 10:09:20.971 16146-16146/? D/SecondActivity: 1024
??從日志中我們可以很明顯的看出,結果竟然是1024,可是我們的確已經在TestActivity中把SIZE的值重新賦值了啊。由此可以看出使用多進程并非那么的簡單。
??我們先解釋一下為什么會出現上文中所描述的情況,根本原因我們是知道的,就是因為SecondActivity運行在了另外一個進程中造成的。從系統層面來講,Android會為每一個進程都分配一個獨立的虛擬機,不同的虛擬機在內存分配上有不同的地址空間,這就導致在不同的虛擬機中訪問同一個類的對象會產生多個副本,就拿上面這個例子來說,在com.jyn.test(默認進程)和com.jyn.test:remote進程中都存在一個Project類,并且這兩個類是互不干擾的,在一個進程中修改一個對象的變量值只會影響當前進程,對其他進程是沒有影響的,所以才會造成以上的現象。
一般情況下,使用多進程會造成一下幾個問題:
1.靜態成員和單例模式完全失效。
2.線程同步機制完全失效。
3.SharedPreferences的可靠性下降。
4.Application會多次創建。
??既然使用多進程會出現這么多問題,相應的系統也提供了多種跨進程的通信方法,隨后我們將進一步的去學習如何進行跨進程的通信。