WindySha / my_hexo_blog_comments

This is my hexo blog comments repository.
1 stars 0 forks source link

侵入性低扩展性强的Android换肤框架XSkinLoader的用法及原理 | Windy's Journal #6

Open WindySha opened 5 years ago

WindySha commented 5 years ago

https://windysha.github.io/2018/02/10/%E4%BE%B5%E5%85%A5%E6%80%A7%E4%BD%8E%E6%89%A9%E5%B1%95%E6%80%A7%E5%BC%BA%E7%9A%84Android%E6%8D%A2%E8%82%A4%E6%A1%86%E6%9E%B6XSkinLoader%E7%9A%84%E7%94%A8%E6%B3%95%E5%8F%8A%E5%8E%9F%E7%90%86/

前言Android发展到现在,很多成熟的应用上已经集成了插件式换肤的功能,比如网易云音乐,手机QQ,QQ音乐等等。但是,成熟稳定易用的开源换肤框架并没有出现。 国内最早的插件式换肤框架是Android-Skin-Loader。后面也出现了一些在此基础上的改进版,比如:hongyang的ChangeSkin,andSkin,Android-skin-support,injor,QSkinLoader

xuwenping commented 5 years ago

hi,lz 你的这个库用了,相当不错,感谢分享! 现在在看代码的时候,发现SkinManager的init函数中,调用load,我理解这个意思是去加载上次设置的皮肤,但是看下来init的时候,mSkinAttrMap这个值一直都是空的,所以初始化的时候是不会去加载皮肤的,init里面调用load就没有意义了,不知道我理解的对不对,希望lz有空能回复我,再次感谢!

WindySha commented 5 years ago

@xuwenping hi,lz 你的这个库用了,相当不错,感谢分享! 现在在看代码的时候,发现SkinManager的init函数中,调用load,我理解这个意思是去加载上次设置的皮肤,但是看下来init的时候,mSkinAttrMap这个值一直都是空的,所以初始化的时候是不会去加载皮肤的,init里面调用load就没有意义了,不知道我理解的对不对,希望lz有空能回复我,再次感谢!

不是这样的,init()中的load方法是初始化资源插件apk的Resource对象,这个对象是换肤的核心,换肤的根本就是更换这个Resource。而mSkinAttrMap存在的根本目的是为了换肤后界面立即生效,而不需要重启应用才生效,是用来记录当前正在显示的需要换肤的view。应用刚刚启动,一个view都没有,mSkinAttrMap肯定为空。

qingwadaxia commented 5 years ago

我想咨询一下,为什么在api 28上设置完主题,我在进程杀死app,在打开应用发现还是之前默认的主题,并没有设置成功, 如下是log,应该是28api禁用反射的提示,和这些翻身禁用 有关系么? java.lang.NoSuchFieldException: No field ProgressBar_indeterminateDrawable in class Ljava/lang/Object; (declaration of 'java.lang.Object' appears in /system/framework/core-oj.jar) 2019-08-01 11:19:42.050 21242-21242/? W/System.err: at java.lang.Class.getDeclaredField(Native Method) 2019-08-01 11:19:42.050 21242-21242/? W/System.err: at com.wind.me.xskinloader.util.ReflectUtils.findField(ReflectUtils.java:247) 2019-08-01 11:19:42.050 21242-21242/? W/System.err: at com.wind.me.xskinloader.util.ReflectUtils.findField(ReflectUtils.java:254) 2019-08-01 11:19:42.050 21242-21242/? W/System.err: at com.wind.me.xskinloader.util.ReflectUtils.getField(ReflectUtils.java:51) 2019-08-01 11:19:42.051 21242-21242/? W/System.err: at com.wind.me.xskinloader.util.ReflectUtils.getField(ReflectUtils.java:18) 2019-08-01 11:19:42.051 21242-21242/? W/System.err: at com.wind.me.xskinloader.parser.ProgressBarIndeterminateDrawableStyleParser.getProgressBarIndeterminateDrawableIndex(ProgressBarIndeterminateDrawableStyleParser.java:64) 2019-08-01 11:19:42.051 21242-21242/? W/System.err: at com.wind.me.xskinloader.parser.ProgressBarIndeterminateDrawableStyleParser.parseXmlStyle(ProgressBarIndeterminateDrawableStyleParser.java:34) 2019-08-01 11:19:42.051 21242-21242/? W/System.err: at com.wind.me.xskinloader.StyleParserFactory.parseStyle(StyleParserFactory.java:35) 2019-08-01 11:19:42.051 21242-21242/? W/System.err: at com.wind.me.xskinloader.parser.SkinAttributeParser.parseSkinAttr(SkinAttributeParser.java:41) 2019-08-01 11:19:42.051 21242-21242/? W/System.err: at com.wind.me.xskinloader.SkinInflaterFactory.parseAndSaveSkinAttr(SkinInflaterFactory.java:120) 2019-08-01 11:19:42.051 21242-21242/? W/System.err: at com.wind.me.xskinloader.SkinInflaterFactory.onCreateView(SkinInflaterFactory.java:67)

zhaolong6017 commented 3 years ago

hello,,这个框架对 fragment的支持需要自己重新定义baseFragment吧????目前lib包里没有直接可以继承的类吧;

WindySha commented 3 years ago

@zhaolong6017 hello,,这个框架对 fragment的支持需要自己重新定义baseFragment吧????目前lib包里没有直接可以继承的类吧;

不需要重新定义baseFragment,inflateView的时候更换LayoutInflater就行了。

CaoyangaAndroid commented 3 years ago

你这个框架 多次调用SkinManager.get().loadSkin()放法会导致内存中的重复的Bitmap越来越多,Bitmap得不到释放。在性能低得手机上或者模拟器上,内存溢出。我不知道怎么解决,希望博主能给出解决方案,日志我给博主贴出来: java.lang.OutOfMemoryError: Failed to allocate a 31415052 byte allocation with 5935784 free bytes and 5MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1155) at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:720) at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571) at android.content.res.Resources.getDrawable(Resources.java:771) at com.box.aiqu.util.xskinloader.impl.SkinResourceManagerImpl.getDrawable(SkinResourceManagerImpl.java:135) at com.box.aiqu.util.xskinloader.skinDeployer.ImageDrawableResDeployer.deploy(ImageDrawableResDeployer.java:29) at com.box.aiqu.util.xskinloader.SkinManager.doSkinAttrsDeploying(SkinManager.java:238) at com.box.aiqu.util.xskinloader.SkinManager.deployViewSkinAttrs(SkinManager.java:230) at com.box.aiqu.util.xskinloader.SkinManager.notifySkinChanged(SkinManager.java:217) at com.box.aiqu.util.xskinloader.SkinManager.doNewSkinLoad(SkinManager.java:172) at com.box.aiqu.util.xskinloader.SkinManager.loadNewSkin(SkinManager.java:89) at com.box.aiqu.util.xskinloader.SkinManager.loadSkin(SkinManager.java:78) at com.box.aiqu.util.ChangeSkinUtil.changeSkin(ChangeSkinUtil.java:18)

WindySha commented 3 years ago

@CaoyangaAndroid 你这个框架 多次调用SkinManager.get().loadSkin()放法会导致内存中的重复的Bitmap越来越多,Bitmap得不到释放。在性能低得手机上或者模拟器上,内存溢出。我不知道怎么解决,希望博主能给出解决方案,日志我给博主贴出来: java.lang.OutOfMemoryError: Failed to allocate a 31415052 byte allocation with 5935784 free bytes and 5MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1155) at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:720) at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571) at android.content.res.Resources.getDrawable(Resources.java:771) at com.box.aiqu.util.xskinloader.impl.SkinResourceManagerImpl.getDrawable(SkinResourceManagerImpl.java:135) at com.box.aiqu.util.xskinloader.skinDeployer.ImageDrawableResDeployer.deploy(ImageDrawableResDeployer.java:29) at com.box.aiqu.util.xskinloader.SkinManager.doSkinAttrsDeploying(SkinManager.java:238) at com.box.aiqu.util.xskinloader.SkinManager.deployViewSkinAttrs(SkinManager.java:230) at com.box.aiqu.util.xskinloader.SkinManager.notifySkinChanged(SkinManager.java:217) at com.box.aiqu.util.xskinloader.SkinManager.doNewSkinLoad(SkinManager.java:172) at com.box.aiqu.util.xskinloader.SkinManager.loadNewSkin(SkinManager.java:89) at com.box.aiqu.util.xskinloader.SkinManager.loadSkin(SkinManager.java:78) at com.box.aiqu.util.ChangeSkinUtil.changeSkin(ChangeSkinUtil.java:18)

@CaoyangaAndroid 你这个框架 多次调用SkinManager.get().loadSkin()放法会导致内存中的重复的Bitmap越来越多,Bitmap得不到释放。在性能低得手机上或者模拟器上,内存溢出。我不知道怎么解决,希望博主能给出解决方案,日志我给博主贴出来: java.lang.OutOfMemoryError: Failed to allocate a 31415052 byte allocation with 5935784 free bytes and 5MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1155) at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:720) at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571) at android.content.res.Resources.getDrawable(Resources.java:771) at com.box.aiqu.util.xskinloader.impl.SkinResourceManagerImpl.getDrawable(SkinResourceManagerImpl.java:135) at com.box.aiqu.util.xskinloader.skinDeployer.ImageDrawableResDeployer.deploy(ImageDrawableResDeployer.java:29) at com.box.aiqu.util.xskinloader.SkinManager.doSkinAttrsDeploying(SkinManager.java:238) at com.box.aiqu.util.xskinloader.SkinManager.deployViewSkinAttrs(SkinManager.java:230) at com.box.aiqu.util.xskinloader.SkinManager.notifySkinChanged(SkinManager.java:217) at com.box.aiqu.util.xskinloader.SkinManager.doNewSkinLoad(SkinManager.java:172) at com.box.aiqu.util.xskinloader.SkinManager.loadNewSkin(SkinManager.java:89) at com.box.aiqu.util.xskinloader.SkinManager.loadSkin(SkinManager.java:78) at com.box.aiqu.util.ChangeSkinUtil.changeSkin(ChangeSkinUtil.java:18)

WeakHashMap没有及时释放view导致的问题,需要根据view的生命周期,管理WeakHashMap中的view

CaoyangaAndroid commented 3 years ago

@WindySha

@CaoyangaAndroid 你这个框架 多次调用SkinManager.get().loadSkin()放法会导致内存中的重复的Bitmap越来越多,Bitmap得不到释放。在性能低得手机上或者模拟器上,内存溢出。我不知道怎么解决,希望博主能给出解决方案,日志我给博主贴出来: java.lang.OutOfMemoryError: Failed to allocate a 31415052 byte allocation with 5935784 free bytes and 5MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1155) at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:720) at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571) at android.content.res.Resources.getDrawable(Resources.java:771) at com.box.aiqu.util.xskinloader.impl.SkinResourceManagerImpl.getDrawable(SkinResourceManagerImpl.java:135) at com.box.aiqu.util.xskinloader.skinDeployer.ImageDrawableResDeployer.deploy(ImageDrawableResDeployer.java:29) at com.box.aiqu.util.xskinloader.SkinManager.doSkinAttrsDeploying(SkinManager.java:238) at com.box.aiqu.util.xskinloader.SkinManager.deployViewSkinAttrs(SkinManager.java:230) at com.box.aiqu.util.xskinloader.SkinManager.notifySkinChanged(SkinManager.java:217) at com.box.aiqu.util.xskinloader.SkinManager.doNewSkinLoad(SkinManager.java:172) at com.box.aiqu.util.xskinloader.SkinManager.loadNewSkin(SkinManager.java:89) at com.box.aiqu.util.xskinloader.SkinManager.loadSkin(SkinManager.java:78) at com.box.aiqu.util.ChangeSkinUtil.changeSkin(ChangeSkinUtil.java:18)

@CaoyangaAndroid 你这个框架 多次调用SkinManager.get().loadSkin()放法会导致内存中的重复的Bitmap越来越多,Bitmap得不到释放。在性能低得手机上或者模拟器上,内存溢出。我不知道怎么解决,希望博主能给出解决方案,日志我给博主贴出来: java.lang.OutOfMemoryError: Failed to allocate a 31415052 byte allocation with 5935784 free bytes and 5MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1155) at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:720) at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571) at android.content.res.Resources.getDrawable(Resources.java:771) at com.box.aiqu.util.xskinloader.impl.SkinResourceManagerImpl.getDrawable(SkinResourceManagerImpl.java:135) at com.box.aiqu.util.xskinloader.skinDeployer.ImageDrawableResDeployer.deploy(ImageDrawableResDeployer.java:29) at com.box.aiqu.util.xskinloader.SkinManager.doSkinAttrsDeploying(SkinManager.java:238) at com.box.aiqu.util.xskinloader.SkinManager.deployViewSkinAttrs(SkinManager.java:230) at com.box.aiqu.util.xskinloader.SkinManager.notifySkinChanged(SkinManager.java:217) at com.box.aiqu.util.xskinloader.SkinManager.doNewSkinLoad(SkinManager.java:172) at com.box.aiqu.util.xskinloader.SkinManager.loadNewSkin(SkinManager.java:89) at com.box.aiqu.util.xskinloader.SkinManager.loadSkin(SkinManager.java:78) at com.box.aiqu.util.ChangeSkinUtil.changeSkin(ChangeSkinUtil.java:18)

WeakHashMap没有及时释放view导致的问题,需要根据view的生命周期,管理WeakHashMap中的view 为什么调用SkinManager.get().loadSkin()方法的时候释放不掉内存呢 我看内存里 点击一次 就会多一个Bitmap对象。导致内存里面产生很多相同的Bitmap对象 @WindySha

@CaoyangaAndroid 你这个框架 多次调用SkinManager.get().loadSkin()放法会导致内存中的重复的Bitmap越来越多,Bitmap得不到释放。在性能低得手机上或者模拟器上,内存溢出。我不知道怎么解决,希望博主能给出解决方案,日志我给博主贴出来: java.lang.OutOfMemoryError: Failed to allocate a 31415052 byte allocation with 5935784 free bytes and 5MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1155) at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:720) at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571) at android.content.res.Resources.getDrawable(Resources.java:771) at com.box.aiqu.util.xskinloader.impl.SkinResourceManagerImpl.getDrawable(SkinResourceManagerImpl.java:135) at com.box.aiqu.util.xskinloader.skinDeployer.ImageDrawableResDeployer.deploy(ImageDrawableResDeployer.java:29) at com.box.aiqu.util.xskinloader.SkinManager.doSkinAttrsDeploying(SkinManager.java:238) at com.box.aiqu.util.xskinloader.SkinManager.deployViewSkinAttrs(SkinManager.java:230) at com.box.aiqu.util.xskinloader.SkinManager.notifySkinChanged(SkinManager.java:217) at com.box.aiqu.util.xskinloader.SkinManager.doNewSkinLoad(SkinManager.java:172) at com.box.aiqu.util.xskinloader.SkinManager.loadNewSkin(SkinManager.java:89) at com.box.aiqu.util.xskinloader.SkinManager.loadSkin(SkinManager.java:78) at com.box.aiqu.util.ChangeSkinUtil.changeSkin(ChangeSkinUtil.java:18)

@CaoyangaAndroid 你这个框架 多次调用SkinManager.get().loadSkin()放法会导致内存中的重复的Bitmap越来越多,Bitmap得不到释放。在性能低得手机上或者模拟器上,内存溢出。我不知道怎么解决,希望博主能给出解决方案,日志我给博主贴出来: java.lang.OutOfMemoryError: Failed to allocate a 31415052 byte allocation with 5935784 free bytes and 5MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1155) at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:720) at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571) at android.content.res.Resources.getDrawable(Resources.java:771) at com.box.aiqu.util.xskinloader.impl.SkinResourceManagerImpl.getDrawable(SkinResourceManagerImpl.java:135) at com.box.aiqu.util.xskinloader.skinDeployer.ImageDrawableResDeployer.deploy(ImageDrawableResDeployer.java:29) at com.box.aiqu.util.xskinloader.SkinManager.doSkinAttrsDeploying(SkinManager.java:238) at com.box.aiqu.util.xskinloader.SkinManager.deployViewSkinAttrs(SkinManager.java:230) at com.box.aiqu.util.xskinloader.SkinManager.notifySkinChanged(SkinManager.java:217) at com.box.aiqu.util.xskinloader.SkinManager.doNewSkinLoad(SkinManager.java:172) at com.box.aiqu.util.xskinloader.SkinManager.loadNewSkin(SkinManager.java:89) at com.box.aiqu.util.xskinloader.SkinManager.loadSkin(SkinManager.java:78) at com.box.aiqu.util.ChangeSkinUtil.changeSkin(ChangeSkinUtil.java:18)

WeakHashMap没有及时释放view导致的问题,需要根据view的生命周期,管理WeakHashMap中的view

为什么调用SkinManager.get().loadSkin()方法的时候释放不掉内存呢,我看调用一次这个方法内存里就会多一个相同的Bitmap对象。有没有什么方法可以不用根据view的生命周期来管理WeakHashMap中的view,当调用框架SkinManager.get().loadSkin()方法的时候自动释放内存