日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android 插件化】“ 插桩式 “ 插件化框架 ( 类加载器创建 | 资源加载 )

發布時間:2025/6/17 Android 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 插件化】“ 插桩式 “ 插件化框架 ( 类加载器创建 | 资源加载 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android 插件化系列文章目錄

【Android 插件化】插件化簡介 ( 組件化與插件化 )
【Android 插件化】插件化原理 ( JVM 內存數據 | 類加載流程 )
【Android 插件化】插件化原理 ( 類加載器 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 原理與實現思路 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 類加載器創建 | 資源加載 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 注入上下文的使用 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 獲取插件入口 Activity 組件 | 加載插件 Resources 資源 )
【Android 插件化】“ 插樁式 “ 插件化框架 ( 運行應用 | 代碼整理 )


文章目錄

  • Android 插件化系列文章目錄
  • 一、創建核心依賴庫
  • 二、創建類加載器
  • 三、加載資源
  • 四、插件管理器完整代碼
  • 五、博客資源



參考 【Android 插件化】“ 插樁式 “ 插件化框架 ( 原理與實現思路 ) 中給出的實現思路 , 逐步實現 “ 插樁式 “ 插件化框架 ;




一、創建核心依賴庫



創建 " Android Library " 依賴庫 , 作為 " 插件化 " 框架 核心依賴庫 ;

" 宿主 " 模塊 應用 , 依賴該 “ 插樁式 “ 插件化框架 核心庫 , 依靠該框架核心庫 , 管理 " 插件 " 模塊 編譯打包成的 apk 文件 ;





二、創建類加載器



創建 DexClassLoader , 使用其構造函數創建 , 需要傳入四個參數到構造函數中 ;

package dalvik.system;import java.io.File;public class DexClassLoader extends BaseDexClassLoader {public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) {super((String)null, (File)null, (String)null, (ClassLoader)null);throw new RuntimeException("Stub!");} }

DexClassLoader 構造函數 參數說明 :

String dexPath : 插件包加載路徑 ;

String optimizedDirectory : 開發者指定的 apk 插件包解壓后的緩存路徑 ;

String librarySearchPath : 函數庫的搜索路徑 , 可設置為空 , 忽略 ;

ClassLoader parent : DexClassLoader 加載器的父類加載器 ;


創建插件包解壓后的緩存路徑 : 注意 String optimizedDirectory 參數對應的路徑必須是私有的 ;

// DexClassLoader 的 optimizedDirectory 操作目錄必須是私有的 // ( 模式必須是 Context.MODE_PRIVATE ) File optimizedDirectory = context.getDir("plugin", Context.MODE_PRIVATE);

創建類加載器 : 傳入上述 444 個參數 , 創建類加載器 ;

// 創建 DexClassLoader mDexClassLoader = new DexClassLoader(loadPath, // 加載路徑optimizedDirectory.getAbsolutePath(), // apk 解壓緩存目錄null,context.getClassLoader() // DexClassLoader 加載器的父類加載器 );

注意 : 類加載時 , 只會加載一次 , 如果有重復的類 , 不會重復加載 ;

BootClassLoader 主要作用是加載 JDK 中的字節碼類對象 ;

DexClassLoaderPathClassLoader 主要作用是加載 Android 和 引入的第三方庫 中的字節碼類對象 ;





三、加載資源



加載資源時需要使用到 AssetManager , 但是其構造函數是 隱藏 的 , 被 @Hide 注解 , 開發者無法直接調用 , 需要使用反射進行調用 ;

通過反射創建 AssetManager 對象 : 注意異常捕獲 ;

// 加載資源 try {// 通過反射創建 AssetManagerAssetManager assetManager = AssetManager.class.newInstance(); } catch (IllegalAccessException e) {e.printStackTrace(); } catch (InstantiationException e) {e.printStackTrace(); }

創建 AssetManager 對象后 , 調用 addAssetPath 方法 , 添加資源的路徑 , 用于加載插件包路徑下的資源文件 ;

addAssetPath 也是隱藏方法 , 也是需要使用反射調用該方法 ;

// 通過反射獲取 AssetManager 中的 addAssetPath 隱藏方法 Method addAssetPathMethod = assetManager.getClass().getDeclaredMethod("addAssetPath"); // 調用反射方法 addAssetPathMethod.invoke(assetManager, loadPath);

AssetManager 示例代碼 :

public final class AssetManager implements AutoCloseable {/*** @hide*/@UnsupportedAppUsagepublic AssetManager() {}/*** @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)}* @hide*/@Deprecated@UnsupportedAppUsagepublic int addAssetPath(String path) {return addAssetPathInternal(path, false /*overlay*/, false /*appAsLib*/);} }

獲取 Resources 資源對象 : 通過上述加載插件資源后的 AssetManager 對象來創建 Resources 資源對象 ;

// 獲取資源 mResources = new Resources(assetManager,context.getResources().getDisplayMetrics(),context.getResources().getConfiguration() );

傳入的 DisplayMetrics metrics 和 Configuration config 參數從調用插件包的上下文中獲取 ;


加載資源部分代碼示例 :

首先 , 通過反射創建 AssetManager 對象 ;
然后 , 通過反射調用并執行 AssetManager 對象的 addAssetPath 方法 , 加載插件包資源 ;
最后 , 調用 Resources 構造函數 , 創建資源 , 傳入 AssetManager 對象 和 上下文相關參數 ;

// 加載資源 try {// 通過反射創建 AssetManagerAssetManager assetManager = AssetManager.class.newInstance();// 通過反射獲取 AssetManager 中的 addAssetPath 隱藏方法Method addAssetPathMethod = assetManager.getClass().getDeclaredMethod("addAssetPath");// 調用反射方法addAssetPathMethod.invoke(assetManager, loadPath);// 獲取資源mResources = new Resources(assetManager,context.getResources().getDisplayMetrics(),context.getResources().getConfiguration());} catch (IllegalAccessException e) {// 調用 AssetManager.class.newInstance() 反射構造方法異常e.printStackTrace(); } catch (InstantiationException e) {// 調用 AssetManager.class.newInstance() 反射構造方法異常e.printStackTrace(); } catch (NoSuchMethodException e) {// getDeclaredMethod 反射方法異常e.printStackTrace(); } catch (InvocationTargetException e) {// invoke 執行反射方法異常e.printStackTrace(); }



四、插件管理器完整代碼



插件管理器完整代碼 :

package com.example.plugin_core;import android.content.Context; import android.content.pm.PackageInfo; import android.content.res.AssetManager; import android.content.res.Resources;import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;import dalvik.system.DexClassLoader;/*** 插件化框架核心類*/ public class PluginManager {/*** 類加載器* 用于加載插件包 apk 中的 classes.dex 文件中的字節碼對象*/private DexClassLoader mDexClassLoader;/*** 從插件包 apk 中加載的資源*/private Resources mResources;/*** 插件包信息類*/private PackageInfo mPackageInfo;/*** 加載插件的上下文對象*/private Context mContext;/*** PluginManager 單例*/private static PluginManager instance;private PluginManager(){}/*** 獲取單例類* @return*/public static PluginManager getInstance(){if (instance == null) {instance = new PluginManager();}return instance;}/*** 加載插件* @param context 加載插件的應用的上下文* @param loadPath 加載的插件包地址*/public void loadPlugin(Context context, String loadPath) {this.mContext = context;// DexClassLoader 的 optimizedDirectory 操作目錄必須是私有的// ( 模式必須是 Context.MODE_PRIVATE )File optimizedDirectory = context.getDir("plugin", Context.MODE_PRIVATE);// 創建 DexClassLoadermDexClassLoader = new DexClassLoader(loadPath, // 加載路徑optimizedDirectory.getAbsolutePath(), // apk 解壓緩存目錄null,context.getClassLoader() // DexClassLoader 加載器的父類加載器);// 加載資源try {// 通過反射創建 AssetManagerAssetManager assetManager = AssetManager.class.newInstance();// 通過反射獲取 AssetManager 中的 addAssetPath 隱藏方法Method addAssetPathMethod = assetManager.getClass().getDeclaredMethod("addAssetPath");// 調用反射方法addAssetPathMethod.invoke(assetManager, loadPath);// 獲取資源mResources = new Resources(assetManager,context.getResources().getDisplayMetrics(),context.getResources().getConfiguration());} catch (IllegalAccessException e) {// 調用 AssetManager.class.newInstance() 反射構造方法異常e.printStackTrace();} catch (InstantiationException e) {// 調用 AssetManager.class.newInstance() 反射構造方法異常e.printStackTrace();} catch (NoSuchMethodException e) {// getDeclaredMethod 反射方法異常e.printStackTrace();} catch (InvocationTargetException e) {// invoke 執行反射方法異常e.printStackTrace();}} }



五、博客資源



博客資源 :

  • GitHub : https://github.com/han1202012/Plugin

總結

以上是生活随笔為你收集整理的【Android 插件化】“ 插桩式 “ 插件化框架 ( 类加载器创建 | 资源加载 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。