圖庫和相機在內部實現上實際上是共用的一個app,即Gallery2。它們是Gallery2的兩個不一樣的入口。圖庫的主要功能是展現和管理設備中的或者網絡上的媒體內容(照片、視頻),雖然名字是圖庫,可是其功能不單單限於圖片。其代碼位於packages/apps/Gallery2。android
打開圖庫應用首先看到的是相冊縮略圖,點擊一個相冊後進入這個相冊中的照片的縮略圖,點擊一個照片的縮略圖後進入單張照片模式。這些不一樣的UI之間的切換並無使用不一樣的Activity,而是在同一個Actvity中進行的。這個Activity是GalleryActivity(有兩個GalleryActivity,這兒指的是com.android.gallery3d.app包中的)。佈局文件是main.xml,其主要內容以下:網絡
<RelativeLayout> <include layout=」@layout/gl_root_group」/> <FrameLayout android:id=」@+id/header」/> <FrameLayout android:id=」@+id/footer」/> </RelativeLayout>
接着看gl_root_group.xml,其內容以下:架構
<merge> <GLRootView /> <View android:id=」@+id/gl_root_cover」/> </merge>
這就是圖庫UI實現的特殊之處。GLRootView繼承自GLSurfaceView。實際上Gallery2基於GLSurfaceView實現了一套UI控件,這套UI組件畫在這個GLSurfaceView上。Gallery2的圖庫功能的UI實現沒有采用Android一般的View控件系統。Gallery2實現了GLView、GLRootView、GLCanvas等。GLView就至關於一般Android控件體系中的View,它是全部控件的父類。GLView能夠接收觸摸事件,並把本身畫到GLCanvas上,GLCanvas是一個接口其實現有GLES11Canvas、GLES20Canvas。GLCanvas把本身繪製到GLSurfaceView中。接着說GLView,一個GLView能夠有零個或多個子GLView,它們造成一個樹結構。渲染和事件處理經過這個數結構傳遞。GLView必需加入到(Attach)GLRoot中才能完成渲染和接收事件。GLView能夠經過調用GLRoot的requestRender()和requestLayoutContentPane()方法實現GLView樹的渲染和佈局。
GLRootView除了繼承自GLSurfaceView以外還實現了GLRoot接口。是全部GLView的根控件。即整個GLView樹是添加在它上面的,這經過GLRootView的setContentPane方法實現,有些相似於Activity的setContentView。GLView的渲染在GL線程中進行,事件處理在主線程中進行。這兩個線程須要同步。在事件處理和佈局的時候GLRootView會獲取一個鎖,從而避免渲染線程在這個時候執行。這個鎖就是GLRootView中的mRenderLock。
總結一下就是Gallery2不一樣於通常app之處是它的控件從GLView繼承而不是View,GLView渲染在GLSurfaceView中。Gallery2實現了本身的一套UI控件系統。app
根據UI技術分析一節能夠知道圖庫功能界面的切換本質上時GalleryActivity中GLSurfaceView中GLView的切換。或者能夠說GalleryActivity有相冊縮略圖(AlbumSetPage)、相冊照片縮略圖(AlbumPage)、單張照片(PhotoPage)、幻燈片(SlideshowPage)四種不一樣的狀態(ActivityState)。實際上AlbumSetPage、AlbumPage、PhotoPage、SlideshowPage都繼承自ActivityState,而且它們之間的切換由StateManager來管理。每個ActivityState都有一個GLView樹,這個樹的根節點是ActivityState中定義的mContentPane。
對應AlbumSetPage、AlbumPage、PhotoPage、SlideshowPage分別是SlotView、SlotView、PhotoView、SlideshowView。對應的數據適配器分別是AlbumSetDataLoader、AlbumDataLoader、PhotoDataAdapter、SlideshowDataAdapter。用圖形表示以下:
ide
數據適配器(Adapter)是數據到UI的橋樑,鏈接數據源和UI。Gallery2中數據源是MediaSource,MediaSource建立MediaObject實例,GLView渲染的就是一個個的MediaObject。MediaSource由DataManager管理,AlbumSetPage等ActivityState在初始化的時候會經過DataManager獲取一個MediaObject,這個MediaObject就是ActivityState的數據的最終來源,即數據適配器的數據來源。界面(AlbumSetPage等ActivityState的子類)沒有直接和MediaSource打交道,MediaSource被封裝在了DataManager中。
MediaSource的子類有LocalSource、PicasaSource、ComboSource(一個組合源,組合了LocalSource和PicasaSource的功能)、ClusterSource等。MediaObject有兩個子類MediaSet和MediaItem。MediaSet是一個集合類,其元素是MediaItem類型。MediaSet又有子類LocalAlbumSet、ClusterAlbumSet、ComboAlbumSet、LocalAlbum、ClusterAlbum、ComboAlbum等。MediaItem又有子類LocalMediaItem、UriImage等。數據模型用圖形表示就是:
佈局