超有用的Android開發技巧:攔截介面View建立
highlight: vs theme: devui-blue
攜手創作,共同成長!這是我參與「掘金日新計劃 · 8 月更文挑戰」的第20天,點選檢視活動詳情
本篇文章主要是分析如何攔截
Activity
中View
的建立流程,實現無感知的使用自定義View替換指定的系統View,這對於換膚、埋點設計等等將是非常有幫助的一種方式。
LayoutInflater.Factory2
是個啥?
Activity
內介面的建立是由LayoutInflater
負責,LayoutInflater
最終會交給內部的一個型別為LayoutInflater.Factory2
的factory2
成員變數進行建立。
這個屬性值可以外部自定義傳入,預設的實現類為AppCompatDelegateImpl
:
然後在AppCompatActivity
的初始化構造方法中向LayoutInflater
注入AppCompatDelegateImpl
:
常見的ImageView
、TextView
被替換成AppcompatImageView
、AppCompatTextView
等就是藉助AppCompatDelegateImpl
進行實現的。
這裡有個實現的小細節,在initDelegate()
方法中,呼叫了addOnContextAvailableListener()
方法傳入一個監聽事件實現的factory2注入,這個addOnContextAvailableListener()
方法有什麼魅力呢?
addOnContextAvailableListener()
是幹啥用的?
咱們先看下這個方法是幹啥用的:
最終是將這個監聽物件加入到了ContextAwareHelper
類的內部mListeners
集合中,咱們接下里看下這個監聽物件集合最終是在哪裡被呼叫的。
可以看到,這個集合最終在ComponetActivity
的onCreate()
方法中呼叫,請注意,這個呼叫時機還是在父類的super.onCreate()
方法前進行呼叫的。
所以我們可以得出結論,addOnContextAvailableListener()
新增的監聽器將在父類onCreate()
方法前進行呼叫。
這個用處的場景還是比較多的,比如我們設定Activity
的主題就必須在父類的onCreate()
方法前呼叫,藉助這個監聽,可以輕鬆實現。
程式碼實戰
請注意,這個
factory2
的設定必須在Activity
的onCreate()
方法前呼叫,所以我們可以直接藉助addOnContextAvailableListener()
進行實現,也可以重寫onCreate()
方法在指定位置實現。當然了,前者更加的靈活,這裡我們還是以後者進行舉例。
```kotlin override fun onCreate(savedInstanceState: Bundle?) { LayoutInflaterCompat.setFactory2(layoutInflater, object : LayoutInflater.Factory2 { override fun onCreateView( parent: View?, name: String, context: Context, attrs: AttributeSet ): View? {
return if (name == "要替換的系統View名稱") {
CustumeView()
} else delegate.createView(parent, name, context, attrs)
}
})
} ```
請注意,這裡也有一個實現的小細節,如果當某個系統View不屬於我們要替換的View,請繼續委託給AppCompatDelegateImpl
進行處理,這樣就保證了實現系統元件特有功能的前提下,又能完成我們的View替換工作。
統一所有介面View的替換工作
如果要替換View的介面非常多,一個Activity一個Activity替換過去太麻煩 ,這個時候就可以使用我們經常使用到的Application
的registerActivityLifecycleCallbacks()
監聽所有Activity
的建立流程,其中我們用到的方法就是onActivityPreCreated()
:
``` registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks { override fun onActivityPreCreated(activity: Activity, savedInstanceState: Bundle?) { LayoutInflaterCompat.setFactory2(activity.layoutInflater, object : LayoutInflater.Factory2 { override fun onCreateView( parent: View?, name: String, context: Context, attrs: AttributeSet ): View? {
return if (name == "要替換的系統View名稱") {
CustumeView()
} else (activity as? AppCompatActivity)?.delegate?.createView(parent, name, context, attrs) ?: null
}
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
TODO("Not yet implemented")
}
})
}
} ```
不過這個Application.ActivityLifecycleCallbacks
介面要重寫好多無用的方法,太麻煩了,之前寫過一篇關於介面優化相關的文章嗎,詳情可以參考:介面使用額外重寫的無關方法太多?優化它
總結
之前看過很多換膚、埋點統計上報等相關文章,多多少少都介紹了向AppCompatActivity
中注入factory2
攔截系統View建立的思想,我們設定還可以藉助此實現介面黑白化的效果,非常的好用,每個開發者都應該去了解掌握的知識點。
- kotlin密封sealed class/interface的迭代之旅
- 2022年12月12日—2022年12月25日Android精品文章一覽
- Sqlite簡易效能優化方案,給你的應用插上“翅膀”
- 築基篇:設定介面的開發利器Preference Library,瞭解一下~
- Android訊息機制完整的執行流程,瞭解一下
- 你可能需要了解下的Android開發技巧(二)
- 超有用的Android開發技巧:攔截介面View建立
- Handler建立的幾個必備知識點,瞭解一下
- Android訊息機制中Message常用的幾種監控方式
- 數見不鮮的RecyclerView使用技巧,你瞭解嗎(一)?
- 常用到的幾個Kotlin開發技巧,減少對業務層程式碼的入侵
- 超好用的官方core-ktx庫,瞭解一下(終)~
- Take a look,從delay()方法看協程的掛起與恢復
- 超好用的官方core-ktx庫,瞭解一下~
- 官方core-ktx庫能對SparseArray系列、Pair開發帶來哪些便利?
- 官方core-ktx庫能對富文字Span開發帶來哪些便利2
- 你需要了解的官方core-ktx庫能對開發帶來哪些便利1
- LeakCanary如何監聽Fragment、Fragment View、ViewModel銷燬時機?
- 非反射動態設定TabLayout指示器的寬度
- 探究EventBus粘性事件實現機制