Android 7.0 Gallery圖庫源碼分析1 - 初識Gallery源碼

分析一個項目的源代碼時,第一件事就是查看清單文件,找到程序入口,咱們從Gallery2源碼的清單文件中能夠看到GalleryActivity是此應用的啓動Activity。java

1 <activity android:name="com.android.gallery3d.app.GalleryActivity" android:label="@string/app_name"
2                 android:configChanges="keyboardHidden|orientation|screenSize">
3             <intent-filter>
4                 <action android:name="android.intent.action.MAIN" />
5                 <category android:name="android.intent.category.DEFAULT" />
6                 <category android:name="android.intent.category.LAUNCHER" />
7                 <category android:name="android.intent.category.APP_GALLERY" />
8             </intent-filter>
找到GalleryActivity,它繼承自AbstractGalleryActivity,實現OnCancelListener,OnCancelListener暫時不用考慮,它只是處理dialog防止內存泄漏,咱們首先查看onCreate方法

 

 1 @Override
 2     protected void onCreate(Bundle savedInstanceState) {
 3         super.onCreate(savedInstanceState);
 4         requestWindowFeature(Window.FEATURE_ACTION_BAR);
 5         //使用ActionBar的覆蓋模式
 6         requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
 7 
 8         if (getIntent().getBooleanExtra(KEY_DISMISS_KEYGUARD, false)) {
 9             //加載佈局以前解除鎖屏
10             getWindow().addFlags(
11                     WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
12         }
13         //加載佈局
14         setContentView(R.layout.main);
15 
16         if (savedInstanceState != null) {
17             getStateManager().restoreFromState(savedInstanceState);
18         } else {
19             //根據Intent類型初始化
20             initializeByIntent();
21         }
22     }

 

咱們首先分析佈局,找到R.layout.mainandroid

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2         android:id="@+id/gallery_root"
 3         android:orientation="vertical"
 4         android:layout_width="match_parent"
 5         android:layout_height="match_parent">
 6     <include layout="@layout/gl_root_group"/>
 7     <FrameLayout android:id="@+id/header"
 8             android:visibility="gone"
 9             android:layout_alignParentTop="true"
10             android:layout_width="match_parent"
11             android:layout_height="wrap_content"/>
12     <FrameLayout android:id="@+id/footer"
13             android:visibility="gone"
14             android:layout_alignParentBottom="true"
15             android:layout_alignParentLeft="true"
16             android:layout_alignParentRight="true"
17             android:layout_width="match_parent"
18             android:layout_height="wrap_content"/>
19 </RelativeLayout>

 



根據id咱們能夠判斷layout/gl_root_group這個佈局應該是最主要的,用來顯示主要內容,header和footer暫且無論。gl_root_group是經過include標籤來引用的,咱們找到此佈局。app

 1 <merge xmlns:android="http://schemas.android.com/apk/res/android">
 2     <com.android.gallery3d.ui.GLRootView
 3             android:id="@+id/gl_root_view"
 4             android:layout_width="match_parent"
 5             android:layout_height="match_parent"/>
 6     <View android:id="@+id/gl_root_cover"
 7             android:layout_width="match_parent"
 8             android:layout_height="match_parent"
 9             android:background="@android:color/black"/>
10 </merge>

 


它有兩個佈局。第一個是GLRootView,它繼承自GLSurfaceView,也就是說它是使用OpenGL ES來繪製界面,它也是整個界面的核心;第二個是View,根據它的id能夠看出它是覆蓋在GLRootView上的,至於它的做用咱們在GLRootView的onDrawFrame方法中能夠發現下面這段代碼,它是應用第一次繪製界面時覆蓋在SurfaceView上面,防止第一次繪製時SurfaceView變透明,影響美觀,以後都會隱藏此View。ide

 1 // We put a black cover View in front of the SurfaceView and hide it
 2 // after the first draw. This prevents the SurfaceView being transparent
 3 // before the first draw.
 4 if (mFirstDraw) {
 5             mFirstDraw = false;
 6             post(new Runnable() {
 7                     @Override
 8                     public void run() {
 9                         View root = getRootView();
10                         View cover = root.findViewById(R.id.gl_root_cover);
11                         cover.setVisibility(GONE);
12                     }
13                 });
14         }

 



咱們接着看GLRootView,它繼承自GLSurfaceView,因此它繪製界面核心就是下面三個方法。工具

 1 public class GLRootView extends GLSurfaceView
 2         implements GLSurfaceView.Renderer, GLRoot {
 3     @Override
 4     public void onSurfaceCreated(GL10 gl1, EGLConfig config) {
 5         //Suface建立好會回調此方法,通常這個方法都是作些繪製界面的準備工做
 6     }
 7 
 8     @Override
 9     public void onSurfaceChanged(GL10 gl1, int width, int height) {
10         //Suface改變時回調此方法,好比橫豎屏轉換等,這裏面通常是從新設置界面size等
11     }
12 
13     @Override
14     public void onDrawFrame(GL10 gl) {
15        //每繪製一幀都會回調此方法,也就是說你想繪製三角形仍是紋理貼圖等都是在這方法裏面實現。
16 
17         try {
18             //這個方法是實際繪製界面的
19             onDrawFrameLocked(gl);
20         } finally {
21             mRenderLock.unlock();
22         }
23     }
24 }

 


咱們接着查看onDrawFrameLocked方法佈局

 1 private void onDrawFrameLocked(GL10 gl) {
 2         ......
 3         //mContentView是GLView類型,mCanvas是GLCanvas類型,這是繪製界面的主要工具
 4         if (mContentView != null) {
 5            mContentView.render(mCanvas);
 6         } else {
 7             // Make sure we always draw something to prevent displaying garbage
 8             mCanvas.clearBuffer();
 9         }
10         ......
11     }

 



如今講講GLView和GLCanvas這兩個類,GLView是界面顯示的UI組件,圖庫界面是有不少個小控件組成的,GLView就是這些小控件的基類,它能夠渲染到GLCanvas上,而且接受觸摸事件。GLCanvas就是一個畫布,GLView的size等定義好了怎麼顯示到界面上呢?其實就是經過GLCanvas來實現,GLCanvas是一個接口,它最終是使用OpenGL ES的GLES20.glDrawArrays(type, 0, count)來繪製每一個GLView,它能夠繪製直線、矩形等形狀,沒學過OpenGL ES的能夠參考我以前的文章,對OpenGL ES有個大概瞭解。post

GLView的子類在com.android.gallery3d.ui目錄裏,以view.java結尾的都是它的子類,像EdgeView、PhotoView、ScrollBarView、SlideshowView、SlotView、TileImageView、UndoBarView等,每一個表明一種UI組件類型。ui

GLCanvas有GLES11Canvas和GLES20Canvas兩個子類,GLES11Canvas表明OpenGL ES 1.1以前的版本,使用固定管線繪圖,這個版本太老能夠不考慮了;GLES20Canvas表明OpenGL ES 2.0以後的版本,使用shader語言實現繪圖,如今通常都是使用它。spa

如今就將這些,至於GLView和GLCanvas的細節後面再詳解。

3d

相關文章
相關標籤/搜索