概述
上一篇 C#移動跨平臺開發(1)環境準備釋出之後不久,無獨有偶,微軟宣佈了開放.NET框架原始碼並且會為Windows、Mac和Linux開發一個核心執行時(Core CLR),這也是開源的!IT媒體網站紛紛轉載,部落格園的C#開發者們熱淚盈眶(泥煤都等這一天好久了!)
與此同時VS2015預覽版更是直接整合了Android模擬器,但是其實裡面並沒有說整合IOS模擬器,我不知道大家是怎麼得出可以直接用VS來開發Android和IOS應用的。不管怎麼說,這都是個好訊息。那麼問題來了,C#如何來開發Android和IOS應用?微軟會怎麼做我們不確定,但是我們倒是可以來看看Xamarin是如何做的。
Android系統架構
我想下面這張圖做Android開發的同學應該很熟悉,下面我們就通過來了解Android系統的架構入門來看看Xamarin會怎麼樣去做?
- Linux Kernel 作業系統層
- Libraries And Android Runtime 各種庫和Android 執行環境
- Application Framework 應用框架層 (由Java編寫)
- Applications 應用程式層(由Java編寫並且在Dalvk虛擬機器來執行)
現在做Android開發的同學只要熟悉這些應用框架層的一些介面和類庫就可以給方便的來實現自己的Android應用程式。
關於Dalvk虛擬機器與Java執行環境的區別
- Dalvik主要是完成物件生命週期管理,堆疊管理,執行緒管理,安全和異常管理,以及垃圾回收等等重要功能。
- Dalvik負責程式隔離和執行緒管理,每一個Android應用在底層都會對應一個獨立的Dalvik虛擬機器例項,其程式碼在虛擬機器的解釋下得以執行。
- 不同於Java虛擬機器執行java位元組碼,Dalvik虛擬機器執行的是其專有的檔案格式
- Dex檔案格式可以減少整體檔案尺寸,提高I/o操作的類查詢速度。
- 是為了在執行過程中進一步提高效能,對dex檔案的進一步優化。
- 所有的Android應用的執行緒都對應一個Linux執行緒,虛擬機器因而可以更多的依賴作業系統的執行緒排程和管理機制
- 有一個特殊的虛擬機器程式Zygote,他是虛擬機器例項的孵化器。它在系統啟動的時候就會產生,它會完成虛擬機器的初始化,庫的載入,預製類庫和初始化的操作。如果系統需要一個新的虛擬機器例項,它會迅速複製自身,以最快的資料提供給系統。對於一些只讀的系統庫,所有虛擬機器例項都和Zygote共享一塊記憶體區域。
大家注意第2點和第7點有助於我們理解Xamarin.Android的工作機制。
Xamarin.Android 架構
Java編寫的Android應用程式通過呼叫 Android.* 和 Java.* 這些名稱空間下的類來實現一些系統的功能包括:聲音、顯示、OpenGl等一些通過Java API不能實現的功能或者說是與硬體、系統平臺相關的功能。那這裡的問題是當我們用C#來編寫的時候,這些功能怎麼去呼叫?C#寫的Android 應用程式又是如何初始化的?
Android Callable Wrappers (ACW)
當一個C#開發的Android程式執行的時候,除了一個Dalvik的虛擬機器例項,還有一個Mono的虛擬機器例項在執行。那個Dalvik虛擬機器實體就像一個宿主,我們的APP在宿主上執行,而我們所有用C#寫的方法都會以ACW的形式被呼叫。在Java程式碼中以native的式式invoke,就像invoke其它C或者C++的程式碼一樣。
Momodroid.exe 在編譯階段會為我們的C#類生成對應的ACW。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
using System; using Android.App; using Android.OS; namespace Mono.Samples.HelloWorld { public class HelloAndroid : Activity { protected override void OnCreate (Bundle savedInstanceState) { base.OnCreate (savedInstanceState); SetContentView (R.layout.main); } } } |
對應生成的ACW程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package mono.samples.helloWorld; public class HelloAndroid extends android.app.Activity { static final String __md_methods; static { __md_methods = "n_onCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handlern" + ""; mono.android.Runtime.register ("Mono.Samples.HelloWorld.HelloAndroid, HelloWorld, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", HelloAndroid.class, __md_methods); } public HelloAndroid () { super (); if (getClass () == HelloAndroid.class) mono.android.TypeManager.Activate ("Mono.Samples.HelloWorld.HelloAndroid, HelloWorld, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "", this, new java.lang.Object[] { }); } @Override public void onCreate (android.os.Bundle p0) { n_onCreate (p0); } private native void n_onCreate (android.os.Bundle p0); } |
大家可以看到上面那個 native的n_onCreate方法最後就會呼叫那個通過mono虛擬機器註冊的Mono.Samples.HelloWorld.OnCreate 方法。
Managed Callable Wrappers (MCW)
上面我們講Dalvik 虛擬機器是我們C#開發的Android應用程式的宿主,它通過ACW來呼叫我們用C#寫的方法。如果我們的這個C#裡面的方法涉及到一些聲音或者系統本身,或者說現在已經有很多成熟的用Java寫的類庫,我們想呼叫怎麼辦? 答案是我們再通過MCW 調回去。在C#執行時中去呼叫Java 稱之為MCW。
Xamarin.Android Framework中有很多就是MCW,關於MCW的建立以及C#與Java整合開發的東西我們後面再細講,包括一個C#開發的Android應用程式是如何被啟動的,我們後面再細講。對於C#開發的Android應用程式來說,效能上面肯定是會有影響,但是影響有多大,我並沒有做過具體測試,所以就不詳述了。後面我們再細細的去對比。
Xamarin.IOS 架構
對於開發者來說,Xamarin.IOS相對於Xamarin.Android就要簡單很多了,我們用C#開發的ios應用程式在被編譯成IL程式碼之後,然後轉交給Apple complier直接編譯成IPhonee的本地機器碼。也就是說C#寫的IPhone應用程式和objective-c 寫的是一樣的。並且Xamarin團隊保證在每一個IOS系統更新的時間同步更新Xamarin.IOS這樣我們就不用擔心被滯後了。
小結
這僅僅是一個粗略的介紹,Xamarin移動跨平臺方案是如何來工作的,還有太多我們沒有涉及。 Xamarn.Forms為多種移動平臺提供了統一的UI(雖然目前還有些比較特別的沒有實現,官方也沒有力推它,用來做一些原型,或者概念驗證可以試一樣,另外如果你的UI確實很簡單,那倒是沒有問題。),當然在Xamarin.Forms不能夠滿足你的要求的時候,可以使用Xamarin.Android和Xamarin.IOS的UI控制元件,這些也是Native的,也就是說在UI方面不會有效能的影響。
就目前來看C#來開發IOS應用更具有優越性,我們要在VS中開發Iphone的應用程式需要配一臺Mac來做編譯。相對而言,開發Android的應用程式就會顯得繁瑣一些,底下還有一些隱藏的東西我們沒有具體的講,包括一個app的建立過程,C#與Java整合在一起開發時候的互動等等,這些問題我們就留在後面慢慢來解決。
參考閱讀
http://developer.xamarin.com/guides/android/under_the_hood/architecture/
http://en.wikipedia.org/wiki/Java_Native_Interface
http://developer.xamarin.com/guides/android/advanced_topics/java_integration_overview/