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


轉載請注明出處:http://blog.csdn.net/lb377463323/article/details/68946581

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

<activity android:name="com.android.gallery3d.app.GalleryActivity" android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation|screenSize">

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.APP_GALLERY" />
</intent-filter>

找到GalleryActivity,它繼承自AbstractGalleryActivity,實現OnCancelListener,OnCancelListener暫時不用考慮,它只是處理dialog防止內存泄漏,我們首先查看onCreate方法

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_ACTION_BAR);
//使用ActionBar的覆蓋模式
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);

if (getIntent().getBooleanExtra(KEY_DISMISS_KEYGUARD, false)) {
//加載布局之前解除鎖屏
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
//加載布局
setContentView(R.layout.main);

if (savedInstanceState != null) {
getStateManager().restoreFromState(savedInstanceState);
} else {
//根據Intent類型初始化
initializeByIntent();
}
}

我們首先分析布局,找到R.layout.main

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gallery_root"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<include layout="@layout/gl_root_group"/>
<FrameLayout android:id="@+id/header"
android:visibility="gone"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<FrameLayout android:id="@+id/footer"
android:visibility="gone"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

</RelativeLayout>

根據id我們可以判斷layout/gl_root_group這個布局應該是最主要的,用來顯示主要內容,header和footer暫且不管。gl_root_group是通過include標簽來引用的,我們找到此布局。

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<com.android.gallery3d.ui.GLRootView
android:id="@+id/gl_root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<View android:id="@+id/gl_root_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"/>
</merge>

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

// We put a black cover View in front of the SurfaceView and hide it
// after the first draw. This prevents the SurfaceView being transparent
// before the first draw.
if (mFirstDraw) {
mFirstDraw = false;
post(new Runnable() {
@Override
public void run() {
View root = getRootView();
View cover = root.findViewById(R.id.gl_root_cover);
cover.setVisibility(GONE);
}
});
}

我們接着看GLRootView,它繼承自GLSurfaceView,所以它繪制界面核心就是下面三個方法。

public class GLRootView extends GLSurfaceView
implements GLSurfaceView.Renderer, GLRoot {

@Override
public void onSurfaceCreated(GL10 gl1, EGLConfig config) {
//Suface創建好會回調此方法,一般這個方法都是做些繪制界面的准備工作
}

@Override
public void onSurfaceChanged(GL10 gl1, int width, int height) {
//Suface改變時回調此方法,比如橫豎屏轉換等,這里面一般是重新設置界面size等
}

@Override
public void onDrawFrame(GL10 gl) {
//每繪制一幀都會回調此方法,也就是說你想繪制三角形還是紋理貼圖等都是在這方法里面實現。

try {
//這個方法是實際繪制界面的
onDrawFrameLocked(gl);
} finally {
mRenderLock.unlock();
}
}
}

我們接着查看onDrawFrameLocked方法

private void onDrawFrameLocked(GL10 gl) {
......
//mContentView是GLView類型,mCanvas是GLCanvas類型,這是繪制界面的主要工具
if (mContentView != null) {
mContentView.render(mCanvas);
} else {
// Make sure we always draw something to prevent displaying garbage
mCanvas.clearBuffer();
}
......
}

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

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

GLCanvas有GLES11Canvas和GLES20Canvas兩個子類,GLES11Canvas代表OpenGL ES 1.1之前的版本,使用固定管線繪圖,這個版本太老可以不考慮了;GLES20Canvas代表OpenGL ES 2.0之后的版本,使用shader語言實現繪圖,現在一般都是使用它。

現在就將這些,至於GLView和GLCanvas的細節后面再詳解。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com