1簡介
Wallpaper裏面有兩個Activity:WallpaperCropActivity(進入界面的步驟:打開圖庫,點擊設置爲壁紙),WallpaperPickerActivity(進入界面的步驟:(1)長按桌面空白處,點擊壁紙;(2)進入設置,點擊顯示,點擊壁紙);WallpaperCropActivity其實是簡易版的WallpaperPickerActivity。
這部分代碼實現功能:
(1)生成縮略圖View列表
(2)利用 openGL異步加載壁紙
(3)獲取壁紙異步設置壁紙
2代碼解析
2.1 適配器模式生成縮略圖View
2.1.1 Google提供了豐富的壁紙來源:
壁紙信息對象 | 壁紙來源 | 獲取壁紙對象集合方法 |
DefaultWallpaperInfo | WallpaperManager | getDefaultWallpaper() |
ResourceWallpaperInfo |
mtkPartner Resources wallpapers.xml |
findBundledWallpapers() getWallpaperArrayResourceId() |
FileWallpaperInfo | systemDir | findBundledWallpapers() |
SavedWallpaperTile | saved_wallpaper_images.db | loadThumbnailsAndImageIdList() |
WallpaperInfo | liveWallpaper | new LiveWallpaperListAdapter(getContext()) |
ThirdPartyWallpaperTile | ThirdPartyActivityEnter | new ThirdPartyWallpaperPickerListAdapter(getContext()) |
2.1.2 加載縮略圖view
利用上表中的數據集合生成Adapter對象,利用populateWallpapersFromAdapter()方法加載對應View上面。這邊應該是邏輯太老了。其實用recycleView一個View對象就可以完成了。2.2加載壁紙背景
2.2.1策略模式處理不同壁紙類型點擊事件
2.2.2壁紙準備
根據流程圖再看一下對象變化,這邊還是挺容易被繞暈的。BitmapRegionDecoder和 BimtapTexture到底在幹啥?然後我看到這個邏輯
方法6 採用模板模式
模板模式和策略模式基本上可以互用,主要區別是繼承和委託。比如WallpaperTileInfo把點擊事件委託給各個子類都實現。而這邊BimtmapSource替所有子類處理了loadInBackground()邏輯。
再根據流程圖,看一下對象變化
這時候我已經完全糊塗了,BitmRegionDecoder和BitmapTexture到底是幹啥的?直到看到這個邏輯。
BitmapRegionDecoder雖然是要加載的大圖。但是我屏幕就這麼大,爲啥要顯示屏幕尺寸以外的圖片,這個不是浪費性能麼?
我就發現這個牛逼的邏輯。手勢觸發移動。我得到圖片的options,我根據區域從BitmapRegionDecoder去獲得BitmapTexture mPreview 紋理。只加載屏幕顯示的區域。
public Bitmap getTile(int level, int x, int y, Bitmap bitmap) {
int tileSize = getTileSize();
int t = tileSize << level;
mWantRegion.set(x, y, x + t, y + t);
if (bitmap == null) {
bitmap = Bitmap.createBitmap(tileSize, tileSize, Bitmap.Config.ARGB_8888);
}
mOptions.inSampleSize = (1 << level);
mOptions.inBitmap = bitmap;
try {
bitmap = mDecoder.decodeRegion(mWantRegion, mOptions);
} finally {
if (mOptions.inBitmap != bitmap && mOptions.inBitmap != null) {
mOptions.inBitmap = null;
}
}
if (bitmap == null) {
Log.w("BitmapRegionTileSource", "fail in decoding region");
}
return bitmap;
}
2.3 openGL加載圖片
這邊獲得值都採用了同步鎖,但是我不知道該怎麼畫圖,而且這邊邏輯繞的我有點暈,但是大概是因爲如果圖片很大,處理紋理是耗時操作,所以必須加鎖保證能取到值。
這邊我自己也沒理清楚,所以我覺得我也寫不出來什麼。所以放個Android openGL的demo連接。使用方法很簡單。
( 7 )初始化Google封裝的GLSurfaceView
( 8 )設置渲染器 TiledImageRenderer
( 9 )設置加載模式RENDERMODE_WHEN_DIRTY,只有在創建和調用requestRender()時纔會刷新。
(14 ~ 15)通知刷新時,TiledImageRenderer首次會回調onSurfaceCreated,onSurfaceChanged,onDrawFrame。之後如果尺寸不改變,只會觸發
onDrawFrame回調。