上次我们探讨了Android 4.0中Gallery3d中的视频播放器,现在剩下的代码非常的多,我们先整体看下有那些包
com.android.gallery3d.anim;//动画 com.android.gallery3d.app;//应用 com.android.gallery3d.common;//通用 com.android.gallery3d.data;//数据源 com.android.gallery3d.gadget;//小部件 com.android.gallery3d.onetimeinitializer;//小部件 com.android.gallery3d.photoeditor;//编辑图片 com.android.gallery3d.photoeditor.actions;//编辑图片 com.android.gallery3d.photoeditor.filters;// com.android.gallery3d.picasasource;//毕加索 com.android.gallery3d.provider;//provider com.android.gallery3d.settings;//设置 com.android.gallery3d.ui;//UI com.android.gallery3d.util;//通用
我们还是先从app包中的Gallery.java看起吧
public final class Gallery extends AbstractGalleryActivity implements OnCancelListener {}
public class AbstractGalleryActivity extends Activity implements GalleryActivity {}
public interface GalleryActivity extends GalleryContext { public StateManager getStateManager(); public GLRoot getGLRoot(); public GalleryActionBar getGalleryActionBar(); public OrientationManager getOrientationManager(); public TransitionStore getTransitionStore(); }
第二个getGLRoot(),看起来Android还是要用OpenGL来画啊?
第三个是GalleryActionBar,ActionBar是2.3上面没有的东西,一个通用的控件而已,一个条型的控件
第四个是定向管理器,
第五个是过渡存储包,这两个比较难理解,后面再看代码理解吧。
我发现4.0的Gallery原理和2.3里面的非常的像,2.3的理解好了之后,对于4.0的非常有帮助,而且4.0代码非常的庞大,没有基础会容易晕。
我们先按照2.3使用OpenGL的原理来看下,4.0 的Gallery3上的区别。
再AbstractGalleryActivity中我们先看OpenGL的相关内容
@Override protected void onSaveInstanceState(Bundle outState) { mGLRootView.lockRenderThread(); try { super.onSaveInstanceState(outState); getStateManager().saveState(outState); } finally { mGLRootView.unlockRenderThread(); } }
@Override protected void onResume() { super.onResume(); mGLRootView.lockRenderThread(); try { getStateManager().resume(); getDataManager().resume(); } finally { mGLRootView.unlockRenderThread(); } mGLRootView.onResume(); mOrientationManager.resume(); }
@Override protected void onPause() { super.onPause(); mOrientationManager.pause(); mGLRootView.onPause(); mGLRootView.lockRenderThread(); try { getStateManager().pause(); getDataManager().pause(); } finally { mGLRootView.unlockRenderThread(); } MediaItem.getMicroThumbPool().clear(); MediaItem.getThumbPool().clear(); MediaItem.getBytesBufferPool().clear(); }
import com.android.gallery3d.ui.GLRoot; import com.android.gallery3d.ui.GLRootView;
public GLRoot getGLRoot() { return mGLRootView; }
我们看下这两个类都是什么关系
public class GLRootView extends GLSurfaceView implements GLSurfaceView.Renderer, GLRoot {}
而GLRoot只是个接口
public interface GLRoot {}
public void onDrawFrame(GL10 gl) {}
android使用了比较正规的办法dispatchTouchEvent来处理触摸事件,然后在mContentView.dispatchTouchEvent各个页面中(注意没有用Layer,而是用的Page或者说View)
@Override public boolean dispatchTouchEvent(MotionEvent event) { if (!isEnabled()) return false; int action = event.getAction(); if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { mInDownState = false; } else if (!mInDownState && action != MotionEvent.ACTION_DOWN) { return false; } if (mCompensation != 0) { event.transform(mCompensationMatrix); } mRenderLock.lock(); try { // If this has been detached from root, we don't need to handle event boolean handled = mContentView != null && mContentView.dispatchTouchEvent(event); if (action == MotionEvent.ACTION_DOWN && handled) { mInDownState = true; } return handled; } finally { mRenderLock.unlock(); } }
有个问题,说是分发触摸消息,但是没有循环,只有一个调用啊?
是的,Android采用的办法并不是分层,而是分页面的办法,每个界面都在一个页面里面,每次只要切换页面就可以了,切换页面的时候将mContentView的值设置成制定的页面就可以了。我考虑Android想的是分层将很多控件写在一个层里面,靠隐藏和显示切换,这样有点乱。这个改动是比较好的。
那么这个mContentView的值是什么时候修改的呢?
@Override public void setContentPane(GLView content) { if (mContentView == content) return; if (mContentView != null) { if (mInDownState) { long now = SystemClock.uptimeMillis(); MotionEvent cancelEvent = MotionEvent.obtain( now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0); mContentView.dispatchTouchEvent(cancelEvent); cancelEvent.recycle(); mInDownState = false; } mContentView.detachFromRoot(); BasicTexture.yieldAllTextures(); } mContentView = content; if (content != null) { content.attachToRoot(this); requestLayoutContentPane(); } }
在页面的OnResume的时候
public void onResume() { super.onResume(); mIsActive = true; setContentPane(mRootPane);
protected void setContentPane(GLView content) { mActivity.getGLRoot().setContentPane(content); }
看起来,Android的实现更为精致一些,这次就说到这里吧。休息,休息一会,下次再说。