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壁纸准备

这里逻辑比较简单。这个里面又使用与策略模式类似的方法模板模式。
(1         )WallpaperTileInfo各个子类处理点击事件
(2         )生成对应XXXBitmapSource对象 (3~5    )生成LoadRequest对象,利用handler发消息。 (6~8    )处理XXXBitmapSource对象里面的Bitmap,GLUtils判断该Bitmap是否能被加载 (9~12  )生成BitmapRegionTileSource对象,将bitmap封装成BitmapTexture对象 (13~14)openGL加载图片


根据流程图再看一下对象变化,这边还是挺容易被绕晕的。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加载图片

Google为了保证低运行内存,低配置的手机升级版本还拥有较好的用户体验做了不少努力。 首先使用BitmapRegionDecoder加载宽屏壁纸,最大支持2048*2048像素的图片。图片加载很吃内存,很容易oom。 Google采取3个步骤。 (1)独立进程,WallpaperPicker是运行在com.android.launcher3:wallpaper_chooser中。 (2)openGL加载图片,openGL是独立开辟一块内存加载图片,性能优化极高。 (3)界面启动,不通过读流加载壁纸,而是通过配置android:windowShowWallpaper属性,达到加载壁纸的效果,从而降低启动占用的内存。 (4)上面的神逻辑


这边获得值都采用了同步锁,但是我不知道该怎么画图,而且这边逻辑绕的我有点晕,但是大概是因为如果图片很大,处理纹理是耗时操作,所以必须加锁保证能取到值。

这边我自己也没理清楚,所以我觉得我也写不出来什么。所以放个Android openGL的demo连接。使用方法很简单。

(       7       )初始化Google封装的GLSurfaceView

(       8       )设置渲染器 TiledImageRenderer

(       9        )设置加载模式RENDERMODE_WHEN_DIRTY,只有在创建和调用requestRender()时才会刷新。

(14 ~ 15)通知刷新时,TiledImageRenderer首次会回调onSurfaceCreated,onSurfaceChanged,onDrawFrame。之后如果尺寸不改变,只会触发

 onDrawFrame回调。

2.4 设置壁纸

设置壁纸与处理壁纸点击事件的逻辑是同一个逻辑。这里Google采用AsyncTask BitmapCropTask处理异步加载和UI刷新逻辑。




更多相关文章

  1. ANDROID _EGL
  2. Android绚丽加载效果视图(loading)控件
  3. Android(安卓)ListView下拉刷新上拉自动加载更多DEMO示例
  4. arcgis for android 100.2加载离线地图随笔
  5. Android:WebView加载url网页显示不完整解决办法
  6. Android(安卓)7.1.2(Android(安卓)N) Multi-window-mode--多窗口
  7. Android(安卓)Activity的四种加载模式
  8. ClassLoader原理剖析
  9. Android(安卓)LoadingDialog一些问题

随机推荐

  1. eclipse开发使用recyclerview步骤介绍
  2. Mac下Android(安卓)iperf网络测试
  3. android fragment学习4-底部布局扩展TabL
  4. 细读《深入理解 Android(安卓)内核设计思
  5. Android之系统架构
  6. android如何使webview不跳到自带的浏览器
  7. 基于android ndk-r15 生成ffmpeg4.0 .so
  8. Android环境的搭建
  9. Android之异步任务AsyncTask解析XML数据
  10. 二维码扫描(横屏、竖屏、解决竖屏后拉伸问