diff --git a/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/HookEntry.kt b/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/HookEntry.kt index e4cb034d..b5ac99e0 100644 --- a/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/HookEntry.kt +++ b/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/HookEntry.kt @@ -67,6 +67,11 @@ class HookEntry : IYukiHookXposedInit { // 若无和模块频繁交互数据在宿主重新启动之前建议开启 // 若需要实时交互数据建议关闭或从 [YukiHookModulePrefs] 中进行动态配置 isEnableModulePrefsCache = true + // 是否启用当前 Xposed 模块自身 [Resources] 缓存功能 + // 一般情况下模块的 Resources 是不会改变的 - 但是在语言区域更改、分辨率更改等情况下 - 就需要刷新缓存 + // 若无上述需求 - 在宿主重新启动之前建议开启 + // 你可以手动调用 [PackageParam.refreshModuleAppResources] 来刷新缓存 + isEnableModuleAppResourcesCache = true // 是否启用 [Member] 缓存功能 // 为防止 [Member] 复用过高造成的系统 GC 问题 - 此功能默认启用 // 除非缓存的 [Member] 发生了混淆的问题 - 否则建议启用 diff --git a/docs/api/public/PackageParam.md b/docs/api/public/PackageParam.md index be986405..081b4a5f 100644 --- a/docs/api/public/PackageParam.md +++ b/docs/api/public/PackageParam.md @@ -216,6 +216,20 @@ fun resources(): HookResources 请调用 `HookResources.hook` 方法开始 Hook。 +### refreshModuleAppResources [method] + +```kotlin +fun refreshModuleAppResources() +``` + +**变更记录** + +`v1.0.87` `新增` + +**功能描述** + +> 刷新当前 Xposed 模块自身 `Resources`。 + ### loadApp [method] ```kotlin diff --git a/docs/api/public/YukiHookAPI.md b/docs/api/public/YukiHookAPI.md index 9ff5f6e0..00818c61 100644 --- a/docs/api/public/YukiHookAPI.md +++ b/docs/api/public/YukiHookAPI.md @@ -152,12 +152,32 @@ var isEnableModulePrefsCache: Boolean 你可以手动在 `YukiHookModulePrefs` 中自由开启和关闭缓存功能以及清除缓存。 +#### isEnableModuleAppResourcesCache [field] + +```kotlin +var isEnableModuleAppResourcesCache: Boolean +``` + +**变更记录** + +`v1.0.87` `新增` + +**功能描述** + +> 是否启用当前 Xposed 模块自身 `Resources` 缓存功能。 + +为防止内存复用过高问题,此功能默认启用。 + +你可以手动调用 `PackageParam.refreshModuleAppResources` 来刷新缓存。 + +!> 关闭后每次使用 `PackageParam.moduleAppResources` 都会重新创建,可能会造成运行缓慢。 + #### isEnableMemberCache [field] ```kotlin var isEnableMemberCache: Boolean ``` - +ø **变更记录** `v1.0.68` `新增` @@ -211,6 +231,7 @@ class HookEntryClass : IYukiHookXposedInit { isDebug = true isAllowPrintingLogs = true isEnableModulePrefsCache = true + isEnableModuleAppResourcesCache = true isEnableMemberCache = true } } @@ -233,6 +254,7 @@ class HookEntryClass : IYukiHookXposedInit { isDebug = true isAllowPrintingLogs = true isEnableModulePrefsCache = true + isEnableModuleAppResourcesCache = true isEnableMemberCache = true } @@ -254,6 +276,7 @@ class HookEntryClass : IYukiHookXposedInit { YukiHookAPI.Configs.isDebug = true YukiHookAPI.Configs.isAllowPrintingLogs = true YukiHookAPI.Configs.isEnableModulePrefsCache = true + YukiHookAPI.Configs.isEnableModuleAppResourcesCache = true YukiHookAPI.Configs.isEnableMemberCache = true } diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt index 245f40c4..e4836b17 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt @@ -31,6 +31,7 @@ package com.highcapable.yukihookapi import android.app.Application import android.content.Context +import android.content.res.Resources import com.highcapable.yukihookapi.YukiHookAPI.configs import com.highcapable.yukihookapi.YukiHookAPI.encase import com.highcapable.yukihookapi.hook.core.finder.ConstructorFinder @@ -139,6 +140,17 @@ object YukiHookAPI { */ var isEnableModulePrefsCache = true + /** + * 是否启用当前 Xposed 模块自身 [Resources] 缓存功能 + * + * - 为防止内存复用过高问题 - 此功能默认启用 + * + * - ❗关闭后每次使用 [PackageParam.moduleAppResources] 都会重新创建 - 可能会造成运行缓慢 + * + * 你可以手动调用 [PackageParam.refreshModuleAppResources] 来刷新缓存 + */ + var isEnableModuleAppResourcesCache = true + /** * 是否启用 [Member] 缓存功能 * diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt index 252846eb..4b448d37 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt @@ -32,6 +32,7 @@ package com.highcapable.yukihookapi.hook.param import android.app.Application import android.content.pm.ApplicationInfo import android.content.res.Resources +import com.highcapable.yukihookapi.YukiHookAPI import com.highcapable.yukihookapi.hook.bean.HookClass import com.highcapable.yukihookapi.hook.bean.HookResources import com.highcapable.yukihookapi.hook.bean.VariousClass @@ -139,7 +140,9 @@ open class PackageParam(@PublishedApi internal var wrapper: PackageParamWrapper? * @return [YukiModuleResources] * @throws IllegalStateException 如果当前 Hook Framework 不支持此功能 */ - val moduleAppResources get() = YukiHookBridge.moduleAppResources ?: error("Current Hook Framework not support moduleAppResources") + val moduleAppResources + get() = (if (YukiHookAPI.Configs.isEnableModuleAppResourcesCache) YukiHookBridge.moduleAppResources + else YukiHookBridge.dynamicModuleAppResources) ?: error("Current Hook Framework not support moduleAppResources") /** * 获得当前使用的存取数据对象缓存实例 @@ -174,6 +177,9 @@ open class PackageParam(@PublishedApi internal var wrapper: PackageParamWrapper? this.wrapper = anotherParam.wrapper } + /** 刷新当前 Xposed 模块自身 [Resources] */ + fun refreshModuleAppResources() = YukiHookBridge.refreshModuleAppResources() + /** * 装载并 Hook 指定、全部包名的 APP * diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt index c712660f..9d07f814 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt @@ -77,6 +77,12 @@ object YukiHookBridge { /** 当前 Xposed 模块自身 [Resources] */ internal var moduleAppResources: YukiModuleResources? = null + /** + * 获取当前 Xposed 模块自身动态 [Resources] + * @return [YukiModuleResources] or null + */ + internal val dynamicModuleAppResources get() = runCatching { YukiModuleResources.createInstance(moduleAppFilePath) }.getOrNull() + /** * 模块是否装载了 Xposed 回调方法 * @@ -185,6 +191,11 @@ object YukiHookBridge { } } + /** 刷新当前 Xposed 模块自身 [Resources] */ + internal fun refreshModuleAppResources() { + dynamicModuleAppResources?.let { moduleAppResources = it } + } + /** * 标识 Xposed API 装载完成 * @@ -204,7 +215,7 @@ object YukiHookBridge { @YukiGenerateApi fun callXposedZygoteLoaded(sparam: IXposedHookZygoteInit.StartupParam) { moduleAppFilePath = sparam.modulePath - moduleAppResources = YukiModuleResources.createInstance(moduleAppFilePath) + refreshModuleAppResources() } /** diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.kt index fc61a38e..968bc4d2 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.kt @@ -53,7 +53,7 @@ class YukiModuleResources(private val baseInstance: XModuleResources) : * @param path Xposed 模块 APK 路径 * @return [YukiModuleResources] */ - fun createInstance(path: String) = YukiModuleResources(XModuleResources.createInstance(path, null)) + internal fun createInstance(path: String) = YukiModuleResources(XModuleResources.createInstance(path, null)) } /**