Wallpaper里面有两个Activity:WallpaperCropActivity(进入界面的步骤:打开图库,点击设置为壁纸),WallpaperPickerActivity(进入界面的步骤:(1)长按桌面空白处,点击壁纸;(2)进入设置,点击显示,点击壁纸);WallpaperCropActivity其实是简易版的WallpaperPickerActivity。
这部分代码实现功能:
(1)生成缩略图View列表
(2)利用 openGL异步加载壁纸
(3)获取壁纸异步设置壁纸
壁纸信息对象 | 壁纸来源 | 获取壁纸对象集合方法 |
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()) |
根据流程图再看一下对象变化,这边还是挺容易被绕晕的。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;
}
这边获得值都采用了同步锁,但是我不知道该怎么画图,而且这边逻辑绕的我有点晕,但是大概是因为如果图片很大,处理纹理是耗时操作,所以必须加锁保证能取到值。
这边我自己也没理清楚,所以我觉得我也写不出来什么。所以放个Android openGL的demo连接。使用方法很简单。
( 7 )初始化Google封装的GLSurfaceView
( 8 )设置渲染器 TiledImageRenderer
( 9 )设置加载模式RENDERMODE_WHEN_DIRTY,只有在创建和调用requestRender()时才会刷新。
(14 ~ 15)通知刷新时,TiledImageRenderer首次会回调onSurfaceCreated,onSurfaceChanged,onDrawFrame。之后如果尺寸不改变,只会触发
onDrawFrame回调。