天天看點

Activity是啥子

百度百科:  https://baike.baidu.com/item/activity/7304419?fr=aladdin

本文我主要通過檢視Activity的實作源碼和推測其設計思想的方法來探讨一下Android的本質是什麼。

Activity恐怖是Android用得最多且是最基本的元件了,估計也是每個學Android的人接觸的第一概念,對于Activity的了解和說法,層出不窮,有人說是一個視窗,有個說是一個活動,但他的本質是什麼呢,官方的說法是Activity一個應用程式的元件,它提供一個螢幕來與使用者互動,以便做一些諸如打電話、發郵件和看地圖之類的事情,原話如下:

An 

Activity

 is an application component that provides a screen with which users can interact in order to do something, such as dial the phone, take a photo, send an email, or view a map.

這句話概括的很好,但我并不認為這就是Activity的本質。

切入主題之前,我們先要了解一下UI系統的職責和原理。所有的圖形界面,無論是什麼UI系統,都要收集使用者的活動,這些活動包括打開和關閉程式,輸入事件等,這樣系統才能針對這些活動做出一些反應,比如程式打開時加載一個資料庫,建立一個網絡連接配接,不過針對這些活動所作出的反應都委托給了具體的應用程式,系統相當于隻是把這些事件或消息轉發給應用程式。下面是一個簡單的圖:

Activity是啥子

這些消息怎麼轉發給程式呢,可以約定好,要求應程式寫一個方法,或如果是C可要求傳入一個回調,Java可以要求程式傳入一個監聽器,總之實作這個功能還是很容易的,但這麼多消息,全部傳到一個方法裡嗎,我想那樣會很慘,那樣可能要求你寫應用程式的時候可能要寫一個長長的swich語句或if語句,是以一般都把這些消息分類,如一種是整個程式的活動的消息,如關閉和打開,還有就是輸入事件,如按鍵滑鼠,每個分類裡的消息還可以再細分,這樣的話,就可以封裝成多個類或接口,每個類有數個方法,之後應用程式重寫這些類方法或實作某個接口,系統就可以通過調用這些類或接口的執行個體發送消息了。

于是問題轉化成了類的設計。在Windows中,有個視窗類來接受一個視窗的活動,系統就可以通過調用視窗類的方法來傳遞消息,這個視窗類既接受打開和關閉的活動,又接受使用者輸入事件。而在Android中而不同,Activity隻接受打開和關閉等的活動,而不會接受輸入事件,那是由Activity内嵌的Window類來接受的,然後轉發給相應View,你有可能會說Activity中有個onKeyDown方法,其實那隻是處理沒人領的按鍵消息才會到達Activity。現在發現Android和Windows分發消息的的差別了吧,這樣化分,每個類的職責更細了,更明确了,當然喽,Android中的消息跟Windows中的可能有點稍小的差別。

現在應該可以很容易的理确Android的每一個生命周期對應的方法(onCreate, onStart...)其實是處理收到的消息,當使用者打開一個Activity的時候,系統(嚴格的說應該是ActivityManager)就會調用onCreate來告訴你這個消息,這個時候你就要加載你的XML布局檔案并做一些初始化。然後離開的時候,就應該把這個Activity銷毀嗎,如果使用者是暫時離開,等下還要回來呢,如果銷毀了那就又得重建立,太浪費時間了(用我們家鄉話說就是太難費神了),是以不能銷毀,但是系統也得通知你使用者離開了(用的是onStop方法),因為可能需要暫停播放視訊。當下次重新進入的時候,系統又會通知你使用者又進來了,這時你可能要恢複播放了,但你有沒有發現,使用者第一次進入和再次進入,你需要做不同的處理,第一次可能是初始化一些資源,第二次可能隻要恢複播放就可以了,是以系統應該告訴你,是第一次進入還是再次進入,于是系統就用了兩個方法,用onCreate告訴你使用者是第一次進入的,用onStart告訴你使用者是再次進入。

不過這還不算完,還有一種情況,使用者是半離開狀态,什麼是半離開呢,都知道Android的界在有全屏,還是非全屏,也有半透明的,這裡的半離開指的就是本界面被一個非全屏或半透明的界面蓋住,總之,你還能看到一點點被蓋的那個界面;全離開就是被全屏的界面蓋住,使用者完全看不到被蓋的。這兩種情況要有可能要差別對待,比如一個播放線上視訊的應用,它可能希望要在使用者半離開時隻暫停播放,不暫停背景下載下傳,而當使用者完全離開時,播放和下載下傳都暫停。是以系統也應該區分這種情況,于是就有了onPause和onResume來表示半離開和從半離開恢複。值得注意的是,Android中全離開包括了半離開,半離開不包括全離開,什麼意思呢,就是即便是全離開,系統也是先調onPause再調onStop,從全離開中恢複,也是調了onStart後還會調onResume,而對于第一次進入,onCreate、onStart、onResume會被依次調用,是以記住,隻要使用者進入,無論是怎麼進入的,都是調用onResume,在這裡恢複播放是再适合不過的了。還有一個onDestory也說一下,就是在銷毀的時候被調用,一般是回收資源或按了傳回鍵會被銷毀。現在清楚了,也順便看一下Android官網的這張圖吧:

Activity是啥子

然後,你可能好奇系統是怎麼調用到你寫的onCreate方法的,有興趣的可以檢視源碼的frameworks/base/core/java/android/app/ActivityThread.java,此類裡面有許多handle***Activity方法,如handleResumeActivity,不過這不是本文章讨論的重點,後續有可能另寫一篇讨論。

下面我們來讨論一下Activity這個類吧,我估計很多人都忽略了Activity類也是一個類,它也可以有構造函數,你還可以在構造函數裡初始化一些東西,不過請注意,Activity的onDestroy被調用時,Activity這個類本身還沒有被銷毀。還一點也很少人忽略,我常問應聘者Activity之間怎麼通信,他們一般都會說Intent或AIDL,如果兩個Activity是同一個應用的,一般是運作在同一程序中的(除非你在AndroidManifest裡配置了讓它們不運作在同一程序),而且一般是同一線程的,是以最簡單的通信方法,莫過于在A Activity中寫一個方法,讓B Activity來調用,你再懶一點,直接通路變量都可以,隻是風格不好。

其它,還要說明的是,一個Activity包含了一個Window,Window才是真正代表一個視窗,也就是說Activity可以沒有Window,那正好是Service了,論據就是剛剛說的ActivityThread類,他的職責包括處理Service,(ActivityThread不是Thread的子類,但他描述了主線程要做的事,具體本文暫不讨論)。Window包含了一個DecorView,這才是真正的界面元素,它是整個View樹的根,你可以試試在Activity裡調用下面這句代碼把整個界面染紅:

[java]  view plain  copy

  1. getWindow().getDecorView().setBackgroundColor(Color.RED);  

另外,還有一個ViewRoot,這個和DecorView經常有人搞混,首先是它對應的類的真正名字是ViewRootImpl,然後,他不是一個View,即他不是View的子類,他的工作與視覺元素無直接關系,但他确定Android View系統的一個重要類,它是負責通信的,如果你知道bridge設計模式就好了解了,這就是一個活生生的例子啊,不過不知道也沒關系,不會阻礙對下文的了解,負責誰跟誰通信呢,是負責你的WindowManager與WindowManagerSerivce之間通信,整個系統的視窗都是由WindowManagerSerivce管理的,因為所有視窗的Z-order,事件分發,都要由一個中樞統一管理才可能有秩序,這就是WindowManagerSerivce的職責了。這樣說,你肯定不能完全了解,要了解還是看代碼吧,路徑:frameworks/base/core/java/android/view/ViewRootImpl.java。其中有一句:

[java]  view plain  copy

  1. mOrigWindowType = mWindowAttributes.type;  
  2.                     res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,  
  3.                             getHostVisibility(), mAttachInfo.mContentInsets,  
  4.                             mInputChannel);  

就是向WindowManagerSerivce注冊了一個輸入事件處理監聽器mInputChannel,具體實作可以寫一篇很長的文章,暫不讨論。

這就是與Activity主要相關的資訊,希望本文加深了你對Activity的了解。

參考資料:

官網指南:http://developer.android.com/guide/components/activities.html

版權聲明:本文為部落客原創文章,轉載請說明出處blog.csdn.net/yanquan345。

繼續閱讀