標籤:android ios 開發
【iOS-Android開發對比】之 APP入口
[圖片 Android vs iOS]
提綱
對比分析iOS,Android的入口,
iOS,Android的介面單元
為什麼要有那樣的生命週期
繼承和抽象類別怎麼寫,例如原廠模式
對象的強弱,iOS的特色
程式入口 (Entry Point)
#首先來看iOS應用的入口:
int main(int argc, char * argv[]){ @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
和所有C程式一樣,main函數是Objective-C程式的入口。雖然這個main方法返回 int,但它並不會真正返回。它會一直存在於記憶體中,直到使用者或者系統將其強制終止.
上面的UIApplicationMain其來自 UIKit,是一個非常重要的函數。
說一下參數,前兩個參數大家都懂。
第三個參數,是UIApplication類名或者是其子類名,如果是nil,則預設使用UIApplication類名。
第四個參數,是AppDelegate類作為應用的委派物件,用來監聽應用生命週期相關的委託方法。
這個UIApplication的核心作用是提供了iOS程式運行期間的控制和協作工作。它建立了App的幾個核心對象如: UIApplicationDelegate UIWindow, UIView,來處理一下過程:
程式入口main函數建立UIApplication執行個體和UIApplication代理執行個體。
從可用Storyboard檔案載入使用者介面
調用AppDelegate自訂代碼來做一些初始化設定
將app放入Main Run Loop環境中來響應和處理與使用者互動產生的事件
這個UIApplication對象在啟動時就設定 Main Run Loop,並且使用它來處理事件和更新基於view的介面, Main Run Loop就是應用程式的主線程。
[圖片 iOS, swift, Android舉牌]
說說Swift的入口:
在Swift語言當中,編譯器不會再去尋找 main 函數作為程式的入口,而是一個main.swift檔案.
該檔案中的第一行代碼就預設為是程式的入口, 可以添加如下代碼:
UIApplicationMain(C_ARGC, C_ARGV, nil, NSStringFromClass(AppDelegate))
沒錯,就是之前提到的UIApplicationMain。這裡 C_ARGC, C_ARGV 全域變數 就是main函數中的
argc, argv。
另外,可以在Swift檔案中添加 @UIApplicationMain 標籤註明項目入口。這樣做會讓編譯器忽略main.swift入口檔案,而將標註有@UIApplicationMain標籤的檔案當做入口檔案。
#再來看看Android的:
Android程式你找不到顯式的main方法
儘管java也有main方法,可Android似乎卻找不到main。
對於這個問題,有很多解釋。
Stackoverflow上有解釋說沒有main是因為不需要main,系統產生activity並調用其方法,應用預設啟動已經把main代替了,因此不需要用main方法。
那麼程式的入口在哪裡? 我們從Application開始看.
每個Android程式的包中,都有一個manifest檔案聲明了它的組件,我們可以看到如下代碼:
<manifest ... <application ... <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
在這個xml寫成的manifest檔案中,<application/> 標籤在最外層。其中,這個標記了android.intent.category.LAUNCHER 的 <activity/> 就是程式啟動的預設介面。但是它們不是真正的入口。
Android應用程式的真正入口為 ActivityThread.main方法
這是一個隱式的入口,代碼做了一定簡化如下:
public static void main(String[] args) { //一些檢測預設值... Looper.prepareMainLooper();// 建立訊息迴圈Looper ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); // UI線程的Handler } AsyncTask.init(); Looper.loop(); // 執行訊息迴圈 throw new RuntimeException("Main thread loop unexpectedly exited"); }
#深入一下:
繼承關係:
java.lang.Object ? android.content.Context ? android.content.ContextWrapper ? android.app.Application
Android的最底層是Linux Kernel, iOS是XNU Kernel,它們有什麼區別呢?
Activity與UIViewController
Android的Activity和Fragment是最基本的介面組成,而IOS是UIViewController。幾乎所有的View和空間都會放在Activity和UIViewController中。
在之上有不少擴充的:
Android: FragmentActivity, AppCompatActivity
IOS: UITableViewController, UICollectionViewController
我們對比一下繼承關係:
Android: Activity->ContextThemeWrapper->ContextWrapper->Context
IOS: UIViewController->UIResponder->NSObject
IOS幾乎所有的基類都是NSObject,Android中也有Object,一般作為Model層對象的基類。
生命週期
這方面資料很多,我簡單說一下:
Android的Activity, onCreate() 中初始化操作, onResume()中可以加一些改變介面和狀態的操作;
IOS的UIViewController, -viewDidLoad 中初始化操作, -viewWillAppear 中可以加一些改變介面和狀態的操作;
對比一下:
Activity: onCreate() –> onStart() –> onResume( )–> 運行態 –> onPause() –> onStop() –> onDestroy()
UIViewController: -viewDidLoad –> -viewWillAppear –> -viewDidAppear –> 運行態 –> -viewWillDisappear –> -viewDidDisappear
這裡補充一個Android的
Fragment:* *onAttach() –> onCreate() –> onCreateView() –> onActivityCreate() –> onStart() –> onResume( )–> 運行態 –> onPause() –> onStop() –> onDestroyView() –> onDestroy() –> onDetach()
Android與IOS都使用 堆棧 的資料結構 儲存Activity和UIViewController.
Android關於Activity的堆棧, 可以搜尋taskAffinity和launchMode。同一應用所有Activity具有相同的親和性(taskAffinity),可通過Itent FLAG設定,也可在AndroidManifest中設定.
IOS中的UINavigationController通過堆棧來UIViewController.
介面跳轉與傳值
Android: Activity可以使用Intent,Fragment使用Bundle。 對於介面回調傳值,通過startActivityForResult()啟動和onActivityResult()接收。
IOS: 在初始化UIViewController對象時,直接給對象中的變數賦值。 對於介面回調傳值,可以自訂介面(Delegate),也可以使用通知(Notification)
結構類型類代碼
//AndroidA.java Class A extends B implements C
//IOSA.h @interface A : B A.m @implementation A <C>
–
強引用和弱引用
Android:
有四種參考型別,強引用(StrongReference),軟引用(SoftReference),弱引用(WeakReference),虛引用(Phantom Reference)。
一般建立的對象都是強引用。所以當記憶體空間不足時,Java虛擬機器寧願拋出OOM異常,也不會隨意回收強引用的對象。
對於軟引用,記憶體空間足夠,記憶體回收行程就不會回收它,可以做圖片的緩衝。
對於弱應用,使用情境例如:在Activity中使用Handler時,一方面需要將其定義為靜態內部類形式,這樣可以使其與外部類(Activity)解耦,不再持有外部類的引用,同時由於Handler中的handlerMessage一般都會多少需要訪問或修改Activity的屬性,此時,需要在Handler內部定義指向此Activity的WeakReference,使其不會影響到Activity的記憶體回收同時,可以在正常情況下訪問到Activity的屬性。
IOS:
使用__weak, __strong用來修飾變數,預設聲明一個對象 __strong。
在強引用中,有時會出現循環參考的情況,這時就需要弱引用來幫忙(__weak)。
強引用持有對象,弱引用不持有對象。
強引用可以釋放對象,但弱引用不可以,因為弱引用不持有對象,當弱引用指向一個強引用所持有的對象時,當強引用將對象釋放掉後,弱引用會自動的被賦值為nil,即弱引用會自動的指向nil。
–
私人和公有
IOS中有-``+方法,-相當於Android中的private,
+相當於Android中的public static。
對於全域變數,IOS是放在AppDelegate中或者使用#define聲明在.h中。
Android同樣,放在Application中 或者類中使用public static。
當然,都可以使用單例類。
基本控制項
對比一些常用的
| Android |
IOS |
| TextView |
UILabel |
| TextEdit |
UITextField UITextView |
| ImageView |
UIImageView |
| Button |
UIButton |
| Switch |
UISwitch |
| ListView |
TableView |
| GridView |
CollectionView |
對比一下繼承:
Android Views -> View
IOS Views -> UIView -> UIResponder -> NSObject
Java實際上任何對象都是直接或間接繼承自Object,寫extends Object和不寫extends是等價的。
因此 Android和IOS的對象, 本質上都是從頂級的Object繼承來的。Amazing~
關於繼承和抽象類別App啟動的堆棧原理如何寫原廠模式App的啟動程式入口
–
文章和代碼一樣,也需要不斷去梳理,不斷迭代。
參考
iOS
http://www.jianshu.com/p/aa50e5350852
http://www.cnblogs.com/ydhliphonedev/archive/2012/07/30/2615801.html
http://swifter.tips/uiapplicationmain/
http://blog.ibireme.com/2015/05/18/runloop/
http://swifter.tips/uiapplicationmain/
Android
http://www.cnblogs.com/lwbqqyumidi/p/4151833.html
https://sites.google.com/site/terrylai14/home/android-context-yuan-li
http://blog.csdn.net/chenzheng_java/article/details/6215986
http://blog.csdn.net/chenzheng_java/article/details/6216621
http://blog.csdn.net/bboyfeiyu/article/details/38555547
其他
Android 程式入口 application onCreate()後都做了什麼,這裡有個歪果仁列印出了onCreate後堆棧顯示的日誌:
MainActivity.onCreate(Bundle) line: 12 Instrumentation.callActivityOnCreate(Activity, Bundle) line: 1047 ActivityThread.performLaunchActivity(ActivityThread$ActivityRecord, Intent) line: 2627 ActivityThread.handleLaunchActivity(ActivityThread$ActivityRecord, Intent) line: 2679 ActivityThread.access$2300(ActivityThread, ActivityThread$ActivityRecord, Intent) line: 125 ActivityThread$H.handleMessage(Message) line: 2033 ActivityThread$H(Handler).dispatchMessage(Message) line: 99 Looper.loop() line: 123 ActivityThread.main(String[]) line: 4627 Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method] Method.invoke(Object, Object...) line: 521 ZygoteInit$MethodAndArgsCaller.run() line: 868 ZygoteInit.main(String[]) line: 626 NativeStart.main(String[]) line: not available [native method]
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
【iOS-Android開發對比】 之 APP入口