[转]Android平台Gallery2应用分析(四)---AlbumSetPage

AlbumSetPage

AlbumSetPage的几个重要成员,如图:

AlbumSetPage刷新AlbumSet,每个看到的相集都是SlotView。而SlotView主要由TiledTexture和label组成。如图:

简单的说,SlotView的绘制过程为:SlotView::render(…) -> renderItem() -> AlbumSetSlotRender::renderSlot() -> renderContent(…) 、renderLabel(…)、renderOverlay(…)。流程图如下:

下面详细说明下SlotView的刷新流程,先看代码流程图,后面附加流程说明:

1) AlbumSetPage的onResume()中,mAlbumSetView.resume()。它会调用mDataWindow.resume()。mDataWindow是AlbumSetSlidingWindow类型。代码如下:

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. public void resume() {  
  2.     mIsActive = true;  
  3.     TiledTexture.prepareResources();  
  4.     for (int i = mContentStart, n = mContentEnd; i < n; ++i) {  
  5.         prepareSlotContent(i);  
  6.     }  
  7.     updateAllImageRequests();  

在for循环中调用prepareSlotContent(i)逐个更新相集显示内容并往mData中记录AlbumSetEntry数据。代码如下:

 

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1.     private void prepareSlotContent(int slotIndex) {  
  2.         AlbumSetEntry entry = new AlbumSetEntry();  
  3.         updateAlbumSetEntry(entry, slotIndex);  
  4.         mData[slotIndex % mData.length] = entry;  
  5. }  

2) 在updateAlbumSetEntry中会获取到相集的title、album、cover、labelLoader以及coverLoader。

 

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. private void updateAlbumSetEntry(AlbumSetEntry entry, int slotIndex) {  
  2.     MediaSet album = mSource.getMediaSet(slotIndex);  
  3.     MediaItem cover = mSource.getCoverItem(slotIndex);  
  4.     int totalCount = mSource.getTotalCount(slotIndex);  
  5.   
  6.     entry.album = album;  
  7.     ……  
  8.     entry.setPath = (album == null) ? null : album.getPath();  
  9.   
  10.     String title = (album == null) ? "" : Utils.ensureNotNull(album.getName());  
  11.     int sourceType = DataSourceType.identifySourceType(album);  
  12.     if (isLabelChanged(entry, title, totalCount, sourceType)) {  
  13.         entry.title = title;  
  14.         entry.totalCount = totalCount;  
  15.         ……  
  16.         if (album != null) {  
  17.             entry.labelLoader = new AlbumLabelLoader(  
  18.                     slotIndex, title, totalCount, sourceType);  
  19.         }  
  20.     }  
  21.   
  22.     entry.coverItem = cover;  
  23.     if (getDataVersion(cover) != entry.coverDataVersion) {  
  24.         ……  
  25.         if (cover != null) {  
  26.             entry.coverLoader = new AlbumCoverLoader(slotIndex, cover);  
  27.         }  
  28.     }  

3) 回头再看第一步中调用的updateAllImageRequests(),代码如下:

 

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1.     private void updateAllImageRequests() {  
  2.         mActiveRequestCount = 0;  
  3.         for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {  
  4.             AlbumSetEntry entry = mData[i % mData.length];  
  5.             if (startLoadBitmap(entry.coverLoader)) ++mActiveRequestCount;  
  6.             if (startLoadBitmap(entry.labelLoader)) ++mActiveRequestCount;  
  7.         }  
  8.         ……  
  9. }  

在for循环中将逐个加载cover、label。startLoadBitmap(entry.coverLoader和startLoadBitmap(entry.labbelLoader从参数类型BitmapLoader看,调用startLoader()会执行各个loader的submitBitmapTask()。详细代码如下:

 

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. AlbumSetSlidingWindow.java  
  2.     private static boolean startLoadBitmap(BitmapLoader loader) {  
  3.         if (loader == null) return false;  
  4.         loader.startLoad();  
  5.         return loader.isRequestInProgress();  
  6. }  
  7. BitmapLoader.java  
  8.     public synchronized void startLoad() {  
  9.         if (mState == STATE_INIT) {  
  10.             mState = STATE_REQUESTED;  
  11.             if (mTask == null) mTask = submitBitmapTask(this);  
  12.         }  
  13.     }  

这个在前面介绍ThreadPool的时候提到过,submit之后会在线程池中执行任务加载图片,从线程池的代码run()中知道完成图片回去后,会调用Listener.onFeatureDone,从future.get中得到Bitmap传给mLoadComplete(mBitmap)。 发送消息MSG_UPDATE_ALBUM_ENTRY调用Loader的updateEntry()。


mRootPane的onLayout调用过程详解:
这个调用过程和Activity的启动流程有关。mRootPane作为一个GLView, 在onResume()时调用setContentPane(mRootPane)设置。在Activity的启动流程中,ActivityThread会调用handleResumeActivity中,先执行performResumeActivity, 后执行wm.addView()。最终会调用到ViewRootImpl的requestLayout() –>View.dispatchAttachedToWindow -> onAttachedToWindow -> GLSurfaceView.onAttachedToWindow -> GLThread.start() -> GLThread.guardedRun() -> onSurfaceCreated()、onSurfaceChanged()、 onDrawFrame() -> onDrawFrameLocked() -> layoutContentPane() -> mContentView.layout()。
其中mContentView即在onResume中SetContentPane()传入的参数mRootPane。

欢迎转载和技术交流,转载请帮忙注明出处,http://blog.csdn.net/discovery_by_joseph,谢谢!

posted @ 2017-02-16 16:39  得即高歌失即休  阅读(245)  评论(0)    收藏  举报