Adroid动态加载Apk-插件化技术框架(动态代理方案)

Android动态加载Apk-插件化技术(动态代理方案)

一.概述

为什么要使用插件化?在开发中,一个项目只会越做越大。初始版本可能是单一功能,后续可能加上各种风马牛不相及的功能。所以我认为插件化可以使得业务分离的更彻底,一人负责哪几个模块,问题也能快速定位。但是也会带来问题:插件和插件之间的交互的复杂性更高、底层支持库因为多个插件需要使用相同的代码可能会变得很大。所以插件化看似解耦了程序员的职责,实际上对于代码质量的要求更高。

要想实现插件化,最快的方法就是找一个第三方框架接入。但是要想真正理解,需要真正自己写一个.下面本文就带大家写一个动态加载插件化的框架

二. 什么是插件化

  1. 主App(宿主App)加载插件apk的实现

  2. 每个业务组件模块形成一个独立的Apk, 然后通过主App动态加载部署业务组件模块Apk的一种方案

三.效果演示图&应用场景

1.效果演示图:

Adroid动态加载Apk-插件化技术框架(动态代理方案) Adroid动态加载Apk-插件化技术框架(动态代理方案)

2.实际开发中,比如微信和支付宝的如下页面就是典型的插件化应用场景

Adroid动态加载Apk-插件化技术框架(动态代理方案) Adroid动态加载Apk-插件化技术框架(动态代理方案)

三.插件化的优点好处

  1. 业务组件解耦,能够实现业务组件模块的热插拔

  2. 更改产品迭代模式,可分为主App和次Apk(动态加载业务组件模块)

  3. 改善产品更新过程,可以在不影响用户的情况下实现业务组件模块更新以及重要Bug修复

  4. 减轻主App的内存和CPU占用,提高应用的性能.

四.插件化的思想

动态加载Apk的主要思想是:主App是被系统(PMS)安装,被系统(AMS)调用,整个过程都是由系统提供的,而插件Apk并非一个真正的Apk,只是一个打包成Apk的一个组件模块,因为它并非被系统安装调用.简言之,需要讲插件Apk看成一个”非Apk”文件,只是一个结构比较复杂的压缩打包成Apk格式的文件.调用插件即用某种特殊技术手段打开文件并执行其相关代码.

五.插件化的步骤-分析主App

1.主APp打包完成解压后,会有dex,images,xml,asset等类型文件

2.Dex靠PathClassLoader加载运行

3.图片以及xml等资源依靠Resources&AssetManager加载管理

六.插件化的实现流程

Adroid动态加载Apk-插件化技术框架(动态代理方案)

六. 插件化的代码实现步骤

1.创建DexClassLoader加载插件化Apk相关代码,核心代码如下:

java;gutter:true /*<em>' * 创建DexClassLoader </em>/ private DexClassLoader createDexClassLoader(String apkPath) { File file = mContext.getDir("dex",Context.MODE_PRIVATE); return new DexClassLoader(apkPath,file.getAbsolutePath(),null,mContext.getClassLoader()); }</p> <pre><code> 2.创建Resources&AssetManager来加载插件化Apk的资源 ;gutter:true
/**
* 获取到插件中的Resource
*/
private Resources createResources(AssetManager am) {
Resources resources = mContext.getResources();
return new Resources(am,resources.getDisplayMetrics(),resources.getConfiguration());
}

/**
* 获取插件的AssetManager
*/
private AssetManager createAssetManager(String apkPath) {
try {
AssetManager am = AssetManager.class.newInstance();
Method method = AssetManager.class.getDeclaredMethod("addAssetPath",String.class);
method.invoke(am,apkPath);
return am;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}

3.管理插件Apk里的组件(如Activity)的生命周期

java;gutter:true package com.czm.pluginlib;</p> <p>import android.app.Activity; import android.content.Intent; import android.os.Bundle;</p> <p>/** * Created by caizhiming on 2018/3/3.</p> <p>*/</p> <p>public interface IPlugin {</p> <pre><code>int FROM_INTERNAL = 0;//内部跳转 int FROM_EXTERNAL = 1;//外部跳转 void attach(Activity activity); void onCreate(Bundle bundle); void onStart(); void onRestart(); void onActivityResult(int requestCode, int resultCode, Intent data); void onResume(); void onPause(); void onStop(); void onDestroy(); </code></pre> <p>}</p> <pre><code> 4.通过代理模式实现对插件Apk里面组件的管理 ;gutter:true
@Override
protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mClassName = getIntent().getStringExtra("className");
mPluginApk = XCPluginManager.getInstance().getPluginApk();

launchPluginActivity();
}

private void launchPluginActivity() {
if(mPluginApk == null){
throw new RuntimeException("请先加载插件Apk");
}
try {
//clazz 就是Activity的实例对象,但是该对象没有生命周期,没有上下文环境
Class clazz = mPluginApk.mDexClassLoader.loadClass(mClassName);
Object object = clazz.newInstance();
if(object instanceof IPlugin) {
mIPlugin = (IPlugin) object;
mIPlugin.attach(this);
Bundle bundle = new Bundle();
bundle.putInt("FROM",IPlugin.FROM_EXTERNAL);
mIPlugin.onCreate(bundle);
}
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public Resources getResources() {
if(mPluginApk != null) {
return mPluginApk.mResources;
} else {
return super.getResources();
}
}

@Override
public AssetManager getAssets() {
if(mPluginApk != null) {
return mPluginApk.mAssetManager;
}else {
return super.getAssets();
}
}

@Override
public ClassLoader getClassLoader() {
if(mPluginApk != null) {
return mPluginApk.mDexClassLoader;
}else {
return super.getClassLoader();
}
}

以上就是实现插件化的主要过程步骤,具体细节优化读者可以自己扩展优化补充.

七.项目代码目录结构图

Adroid动态加载Apk-插件化技术框架(动态代理方案)

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

Original: https://www.cnblogs.com/demodashi/p/10503465.html
Author: demo例子集
Title: Adroid动态加载Apk-插件化技术框架(动态代理方案)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/551605/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 什么是精准卫星授时?什么是NTP网络时间服务器?

    什么是精准卫星授时?什么是NTP网络时间服务器? 什么是精准卫星授时?什么是NTP网络时间服务器? 京准电子科技官微——ahjzsz 时间同步技术在所有网络应用中都是至关重要的,从…

    技术杂谈 2023年6月21日
    0126
  • Java中流水编号的生成

    在开发中,遇到这样一个需求,在介质资料新增时,需要生成一个介质编号,格式为”JZ+yyyyMMdd+4位递增数字”先是使用百度找寻解决方法。解决方法 里面的…

    技术杂谈 2023年7月24日
    0105
  • 新接口开发-切流

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/shoshana-kong/p/16498607.htm…

    技术杂谈 2023年6月1日
    0107
  • checking for tgetent()… configure: error: NOT FOUND!

    今天centos出现了下面的异常: checking for tgetent()… configure: error: NOT FOUND! You need to insta…

    技术杂谈 2023年6月1日
    0116
  • [学习笔记]Java异常处理

    程序运行时,可能会发生各种错误,一些错误是可以避免的,还有些错误是随机出现的且不可避免,一个健壮的程序必须能够处理这些错误; Java内置一套异常处理机制,使用异常来表示错误; 异…

    技术杂谈 2023年7月24日
    086
  • kettle插入更新

    kettle实现若主键存在则更新,若主键不存在则插入 Original: https://www.cnblogs.com/cheng9999/p/14085922.htmlAuth…

    技术杂谈 2023年7月24日
    094
  • PgSQL-||-连字符

    (PgSQL)连字符 || — 22.22& select 22.22||’%’ as 值; Original: https://www.cnblogs.com/a999…

    技术杂谈 2023年6月21日
    0101
  • iOS 分类(Category)和扩展(Extension)

    Extension:扩展, 延展, 匿名分类;放在.m文件中;声明私有属性; (不对子类暴露)声明私有方法;声明私有成员变量; 分类( )扩展(Extension) 运行时决议 编…

    技术杂谈 2023年5月30日
    092
  • Linux下一键安装Python3&更改镜像源&虚拟环境管理技巧

    前言 之前分享过一篇《Linux系统自带Python2&yum的卸载及重装;》,介绍了如何卸载及重装Linux(CentOS)自带的的Python2.7。今天主要介绍如何在…

    技术杂谈 2023年7月24日
    0116
  • elasticsearch-7.2.1启动报错

    1、elasticsearch-7.2.1启动报错,the default discovery settings are unsuitable for production use…

    技术杂谈 2023年5月31日
    0115
  • HIT软构博客2-java异常和final语法

    final的用法: 修饰变量:final关键字修饰的基本数据类型变量称为常量,不可更改。 final修饰的引用类型是不能改变其引用地址的,但可以改变地址内部属性。 修饰方法:fin…

    技术杂谈 2023年7月11日
    0103
  • 平台接口建设规范

    建设目标 平台接口建设规范旨在为接口开发、测试、使用划定一个框架边界,明确技术目标与要求,并要求提供完备的接口文档说明,为自有平台与第三方平台提供数据及服务支持。 建设标准 接口规…

    技术杂谈 2023年7月25日
    099
  • a-form-model的简单例子

    html;gutter:true; 请选择</p> <pre><code> {{ item.text }} 提交 </code>&l…

    技术杂谈 2023年5月31日
    092
  • 如何使gcc输出搜索到的头文件路径?

    答:给gcc加入以下参数即可: -E -Wp,-v posted @2020-12-25 11:44 Jello 阅读(201 ) 评论() 编辑 Original: https:…

    技术杂谈 2023年5月31日
    0113
  • Jmix- 业务系统高效开发的少代码平台

    企业在数字化转型的过程中,都面临将现有的业务流程进行”软件化”的过程。然而,在我们的印象中,通常会觉得针对业务系统的软件开发不是特别高效。这背后有很多原因,…

    技术杂谈 2023年6月21日
    0109
  • 什么是计算机?

    计算机 组成:硬件+软件能按程序运行,自动、告诉处理海量数据的现代化智能电子设备。应用:科学计算、数据处理、自动控制、计算机辅助设计、人工智能、网络(互联网、自己的计算机就是网络的…

    技术杂谈 2023年7月11日
    084
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球