android外掛化主題方案 (上--LayoutInflateFactory的使用)
android外掛化主題方案 (上–LayoutInflateFactory的使用)
標籤(空格分隔): android 主題 面板 外掛化
“做成網易音樂那樣的!”
這次產品經理提出的需求就是像網易音樂那樣可以更換主題面板,當然面板切換很多app都有,產品經理也明確表示需要後臺有面板主題管理能力,所以這次的功能免不了要做成外掛式,不能簡單的在資原始檔編寫多套value的方式實現。
那我們就來一步步的實現吧。
首先,我們先不管外掛化的方式,先來看看如何在不更改已編寫xml的情況下,快速替換view的資源。
setContentView()做了些什麼?
我們知道預設onCreate()
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
這是Activity類中的setContentView()的方法,我們繼續往下看。
@Override public void setContentView(int layoutResID) { if (mContentParent == null) { installDecor(); } else { mContentParent.removeAllViews(); } mLayoutInflater.inflate(layoutResID, mContentParent); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } }
在這裡我們看到了熟悉的充氣類,我們View的建立離不開Inflate,那麼它在建立View的時候做了什麼呢?
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
....
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
...
}
我們找到這個建立view的方法
View createViewFromTag(View parent, String name, Context context, AttributeSet attrs, boolean ignoreThemeAttr) { ... View view; if (mFactory2 != null) { view = mFactory2.onCreateView(parent, name, context, attrs); } else if (mFactory != null) { view = mFactory.onCreateView(name, context, attrs); } else { view = null; } if (view == null && mPrivateFactory != null) { view = mPrivateFactory.onCreateView(parent, name, context, attrs); } ... }
最終我們的view是通過factory進行建立的,
而這個factory就是我們這次需要重點介紹的工具。
/**
* Used with {@code LayoutInflaterCompat.setFactory()}. Offers the same API as
* {@code LayoutInflater.Factory2}.
*/
public interface LayoutInflaterFactory {
/**
* Hook you can supply that is called when inflating from a LayoutInflater.
* You can use this to customize the tag names available in your XML
* layout files.
*
* @param parent The parent that the created view will be placed
* in; <em>note that this may be null</em>.
* @param name Tag name to be inflated.
* @param context The context the view is being created in.
* @param attrs Inflation attributes as specified in XML file.
*
* @return View Newly created view. Return null for the default
* behavior.
*/
public View onCreateView(View parent, String name, Context context, AttributeSet attrs);}
LayoutInflateFactory是一個介面,其只有一個方法,我們重點關注註釋,簡單理解為
提供給你一個鉤子(可以理解為監聽),用以在inflate的時候用名字作為比對,生成對應的View物件進行返回。
so,整個inflate的過程大致就是,xmlParser對xml進行解析,然後傳遞至Factory根據名字生產相對應的View類,然後返回上層進行新增,好了,下面,我們就可以通過實現這個介面,在onCreate()中對生成的view設定各種屬性,這樣,我們就能在xml中書寫固定的資源情況下,動態對view的屬性進行更改。
自定義Factory
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
boolean isSkinEnable = attrs.getAttributeBooleanValue(SkinConfig.NAMESPACE, SkinConfig.ATTR_SKIN_ENABLE, false);
AppCompatDelegate delegate = mAppCompatActivity.getDelegate();
View view = delegate.createView(parent, name, context, attrs);
if (view instanceof TextView && SkinConfig.isCanChangeFont()) {
TextViewRepository.add(mAppCompatActivity, (TextView) view);
}
if (isSkinEnable || SkinConfig.isGlobalSkinApply()) {
if (view == null) {
view = ViewProducer.createViewFromTag(context, name, attrs);
}
if (view == null) {
return null;
}
parseSkinAttr(context, attrs, view);
}
return view;
}
這裡的isSkinEnable我們用來在xml標記該view需要更換面板(自定義名稱空間),下面判斷TextView的部分用來處理更換字型,暫且不看,其餘的建立View的方法於原始碼相同,建立View之後,我們用parseSkinAttr()方法進行view的處理,當然之前我們需要判斷該view是否需要進行切換。
在這個方法中,我們就可以對這個view進行各種處理,更改背景,更改imageView的src等等。
waring
這個factory只用於在介面初始化(比如開啟一個activity)的時候進行主題的更改,在介面被繪製完畢後,我們需要更改這個介面所有view的屬性的話,得呼叫其他方法,所以為了標記那些view需要更改,我們在這個方法中可以定義一個集合,在初始化的時候進行儲存,以方便後續處理。
SkinItem skinItem = new SkinItem();
skinItem.view = view;
skinItem.attrs = viewAttrs;
mSkinItemMap.put(skinItem.view, skinItem);
skinItem就是需要更改的view及其屬性的封裝物件。
替換activity的factory為自定義的factory
@Override
protected void onCreate(Bundle savedInstanceState) {
mSkinInflaterFactory = new SkinInflaterFactory();
mSkinInflaterFactory.setAppCompatActivity(this);
LayoutInflaterCompat.setFactory(getLayoutInflater(), mSkinInflaterFactory);
super.onCreate(savedInstanceState);
changeStatusColor();
}
這裡我建議書寫一個baseActivity,在super.onCreate之前將activity與Factory進行繫結。
這樣在每一個activity啟動之後,建立view時,我們都可以控制到該view的屬性,而我們將這些view儲存之後,我們同樣可以在activity已經建立完畢的條件下,準確找到需要更改的view並對其做相應的修改操作。
相關推薦
android外掛化主題方案 (上--LayoutInflateFactory的使用)
android外掛化主題方案 (上–LayoutInflateFactory的使用) 標籤(空格分隔): android 主題 面板 外掛化 “做成網易音樂那樣的!” 這次產品經理提出的需求就是像網易音樂那樣可以更換主題面板,當然面板切換很多app
Android外掛化的相容性(上):Android O的適配
首先宣告,《Android外掛化開發指南》這本書所介紹的Android底層是基於Android6.0(API level 23)的,而本書介紹的各種外掛化解決方案,以及配套的70多個例子,在Android7.0(API level 24)手機上測試都是能正常工作的。 如果讀者您的手機是
Android外掛化系列第(四)篇---外掛載入機制兩種方案
一、相關概念 1.1、為什麼需要動態載入 這個問題,前面已經介紹過,如下 Android系統使用了ClassLoader機制來進行Activity等元件的載入;apk被安裝之後,APK檔案的程式碼以及資源會被系統存放在固定的目錄(比如/d
Android外掛化最佳方案--Phantom 實踐指南
PhantomTest 滿幫集團外掛化框架Phantom使用演示 Phantom外掛化演示(請star支援) 演示demo下載 注意:請將外掛apk拷貝至sdcard下。 Phantom介紹 Phantom 是滿幫集團開源的一套穩定、靈
Android外掛化——Replugin入門(一)
一、360Replugin簡介 RePlugin是一套完整的、穩定的、適合全面使用的,佔坑類外掛化方案,由360手機衛士的RePlugin Team研發,也是業內首個提出”全面外掛化“(全面特性、全面相容、全面使用)的方案。 其主要優勢有: 極其靈活:主程式無需升級(無
Android外掛化開發教程(一)
1.什麼是外掛化開發首先我們要對外掛化的概念有一個認識:外掛化開發是將整個app拆分成很多模組,這些模組包括一個宿主和多個外掛,每個模組都是一個apk(元件化的每個模組是個lib),最終打包的時候將宿主apk和外掛apk分開或者聯合打包。外掛式開發通俗的講就是把一個很大的app分成n多個
Android外掛化的相容性(中):Android P的適配
Android系統的每次版本升級,都會對原有程式碼進行重構,這就為外掛化帶來了麻煩。 Android P對外掛化的影響,主要體現在兩方面,一是它重構了H類中Activity相關的邏輯,另一個是它重構了Instrumentation。 3.1 H類的變身 3.1
Android 語音播報實現方案(無SDK)
功能描述 類似支付寶收款時候的語音播報功能:當別人掃描你的收款碼,你收到錢之後,就會聽到“支付寶到賬12.55元”的語音播報。 要解決的問題 1.播放單個語音檔案 2.播放完單個語音檔案之後立即播放下一條,這樣才能連續 3.當多個完整的語音
(4.6.29)Android外掛化框架總結
一、概述 所謂外掛化,就是讓我們的應用不必再像原來一樣把所有的內容都放在一個apk中,可以把一些功能和邏輯單獨抽出來放在外掛apk中,然後主apk做到[按需呼叫],這樣的好處是一來可以減少主apk的體積,讓應用更輕便,二來可以做到熱插拔,更加動態化 採集
Android 外掛化分析(3)- Activity啟動流程
在真正分析外掛化技術前,我們必須瞭解一些必要的關於Android四大元件的相關知識。 以Activity為例,我們需要了解Activity啟動過程,才能有效的進行Hook實現外掛化。 以Android 8.1為例 我們啟動一個Activity通常會使用startActi
【轉載】Android外掛化常見衝突解決方案
文章轉自:https://blog.csdn.net/xiangzhihong8/article/details/80278068在Android元件化和外掛化的過程中,經常會遇到狠多的問題,如常見的包依賴衝突,資原始檔依賴衝突等問題,當然,在資原始檔上面,一些元件化框架已為
Android外掛化原理和實踐 (六) 之 四大元件解決方案
在前面的幾篇文章中已經介紹完了Android外掛化的第一和第二個根本問題,就是宿主和外掛的程式碼互相呼叫問題和外掛中資源的讀取問題。現剩下的就是Android外掛化裡最麻煩的第三個根本問題,也就是在外掛中使用四大元件的問題。我們知道,目前外掛中的四大元件要想正常使用就必須要在宿主中的Androi
Android外掛化探索(二)資源載入
前情提要 PathClassLoader和DexClassLoader的區別 DexClassLoader的原始碼如下: public class DexClassLoader extends BaseDexClassLoader {
Android 淘氣三千傳之 —— 外掛化的一點理解(上)
外掛化 這一篇主要是個人對外掛化涉及到的一些基礎知識的理解,內容都比較簡單: 包括以下內容: 目錄: 1、類載入機制 2、Binder機制 3、APP、四大元件的啟動流程 4、APK安裝過程 5、資源的載入過程 6、Hook
【Android 熱修復與外掛化 一】帶你入門Android外掛化(附demo)
本文為博主Colin原創文章,歡迎轉載。 https://blog.csdn.net/colinandroid/article/details/79431502 一. 背景 Android外掛化作為每個合格的Android程式設計師都必須會的技術,被各大廠廣泛使用。隨著各大廠對
包建強的培訓課程(10):Android外掛化從入門到精通
Android外掛化和熱修復 一.簡介 本課程結合講師多年來對Android外掛化技術的潛心研究,以及在千萬級使用者的App上長期實踐經驗,整理而成。本課程從四大元件的外掛化技術講起,中途會詳細剖析Android系統中與外掛化技術有關的底層概念,最後詳細介紹業界流行很廣的外
Android外掛化學習之路(四)之使用外掛中的R資源
res裡的每一個資源都會在R.java裡生成一個對應的Integer型別的id,APP啟動時會先把R.java註冊到當前的上下文環境,我們在程式碼裡以R檔案的方式使用資源時正是通過使用這些id訪問res資源,然而外掛的R.java並沒有註冊到當前的上下文環境,所
Android外掛化原理(一)Activity外掛化
相關文章 前言 四大元件的外掛化是外掛化技術的核心知識點,而Activity外掛化更是重中之重,Activity外掛化主要有三種實現方式,分別是反射實現、介面實現和Hook技術實現。反射實現會對效能有所影響,主流的外掛化框架沒有采用此方式,關於介面實
Android外掛化學習之路(六)之動態建立Activity
靜態代理Activity模式的限制 我們在代理Activity模式一文裡談到啟動外掛APK裡的Activity的兩個難題嗎,由於外掛裡的Activity沒在主專案的Manifest裡面註冊,所以無法經歷系統Framework層級的一系列初始化過程,最終導致獲得
Android外掛化學習之路(一)之動態載入綜述
前段時間,公司專案完成了外掛化的開發,自己也因此學習了很多Android外掛化的知識,於是想把這些內容記錄下來,本次帶來Android外掛化的第一篇:動態載入綜述 背景知識 1.什麼是動態載入? 動態載入技術應由以下幾個部分組成: 1) 應用在執行