換膚框架Android-skin-support 源碼分析

框架源碼地址:?https://github.com/ximsfei/Android-skin-support

基本原理:

Android-skin-support 這個框架的主要思路是:

1. 更換LayoutInflaterFactory,對從xml布局文件要解析出來的 View,如果有相對應(yīng)的支持換膚功能的控件(即實(shí)現(xiàn)SkinCompatSupportable接口的控件),就創(chuàng)建支持換膚功能的控件,然后把這個控件保存起來,如果沒有就創(chuàng)建本來的控件(這個是不保存的);

2. 當(dāng)收到換膚通知的時候,就調(diào)用所有保存里來的控件的applySkin() 進(jìn)行換膚操作。

簡單使用:

1. 初始化:

2. 更換SDcard 上的皮膚:

3. 換回默認(rèn)皮膚:

接下來我們來看看源碼。

一、簡單的框架邏輯:

1. 在 Application 中注冊 SkinActivityLifecycle 監(jiān)聽Activity生命周期;

2. 在 SkinActivityLifecycle 中 onActivityCreated() 設(shè)置

3. getSkinDelegate()中創(chuàng)建SkinCompatDelegate實(shí)例和activity綁定起來存入WeakHashMapmSkinDelegateMap中;

4. 在 SkinCompatDelegate 的回調(diào) onCreateView()(和這個類的實(shí)例綁定的activity的所有view都會走這個函數(shù)) 判斷view是否支持換膚功能,如果支持就存入 List> mSkinHelpers:

View view = createView(parent, name, context, attrs); //創(chuàng)建實(shí)現(xiàn)了SkinCompatSupportable的view實(shí)例

5. 在 SkinActivityLifecycle 的 onActivityResumed() 中創(chuàng)建皮膚更換觀察者,并存入本實(shí)例的WeakHashMapmSkinObserverMap和 SkinCompatManager 的 ArrayListobservers:

創(chuàng)建皮膚觀察者:

6. 在 SkinActivityLifecycle 的 onActivityDestroyed() 中移除與該activity綁定SkinCompatDelegate實(shí)例、SkinObserver:

二、更換皮膚邏輯:

1. 調(diào)用SkinCompatManager.getInstance().loadSkin("night", null, SkinCompatManager.SKIN_LOADER_STRATEGY_BUILD_IN); 啟動一個異步任務(wù)SkinLoadTask:

2. 在異步任務(wù) SkinLoadTask 的 doInBackground() 中根據(jù)strategy調(diào)用不同的皮膚包加載策略類的loadSkinInBackground(), 比如放在Assets皮膚包,這邊就是從Assets復(fù)制皮膚包到getExternalCacheDir()目錄下的skins目錄下。

3. 在異步任務(wù) SkinLoadTask 的 onPostExecute() 調(diào)用 SkinCompatManager 的 notifyUpdateSkin() 通知所有的 SkinObserver 皮膚更新了。

4. 回調(diào) 在 SkinActivityLifecycle 創(chuàng)建的 SkinObserver 實(shí)例的 updateSkin():

5. 調(diào)用 acitvity 對應(yīng)的 SkinCompatDelegate 的 applySkin();

6. 在 SkinCompatDelegate 的 applySkin() 里面遍歷mSkinHelpers(該activity所有的View實(shí)例)的applySkin();

7. 在 View 實(shí)例的 applySkin() 里面實(shí)現(xiàn)了關(guān)于這個控件換皮膚的操作。

三、LayoutInflaterFactory 創(chuàng)建解析出來的view相對應(yīng)的支持換膚功能的控件

createViewFromHackInflater()? 這里創(chuàng)建我們通過addHookInflater() 添加對應(yīng)某個view替換成支持換膚的控件的規(guī)則,可以用來覆蓋框架自帶對應(yīng)的支持換膚的控件,即對應(yīng)某個view,創(chuàng)建我們的自己的控件,不創(chuàng)建框架自帶的控件。

createViewFromInflater() 和上面不同,框架默認(rèn)支持基本常用控件和一些V7包上的一些控件的替換,如果你需要添加其他控件的替換,可以使用addInflater()添加對應(yīng)規(guī)則的View,但是覆蓋不了框架默認(rèn)支持的基本常用控件和一些V7包上的一些控件的替換控件。

基本常用控件的替換:

V7 包只替換了 Toolbar :

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容