一:理解插件化概念
1. 插件化的定义
安卓插件化,作为一种先进的应用架构技术,它打破了传统单体应用开发模式的壁垒,允许将一个完整的应用程序拆分成多个独立的功能模块——插件。每个插件作为一个独立的单元,可以包含用户界面组件、业务逻辑、资源文件以及其它必要组件,并且能够根据需求在运行时动态加载到主应用中。
2. 传统App开发模式的局限性
传统安卓应用开发中,所有的功能模块通常被打包成一个apk文件,一旦应用发布上线,即使只是其中一小部分功能需要更新或新增,也需要用户重新下载并安装整个应用包。这种做法不仅增大了用户流量负担,还可能导致用户更新意愿下降,影响产品迭代速度和用户体验。
此外,大型应用中各功能模块之间相互依赖程度高,不利于团队协作开发和代码维护。而且,一次性加载所有功能也可能导致应用启动耗时增加,占用过多内存资源。
3. 插件化带来的灵活性和可扩展性优势
安卓插件化有效地解决了传统模式的局限性,带来了以下显著优势:
-
动态加载:应用可以根据用户行为或需求,仅加载必要的插件模块,减少首次启动时间和内存消耗,同时支持增量更新,提升用户体验和更新效率。
-
模块化开发:每个插件可以独立编译、测试和打包,不同团队可以并行开发不同的功能模块,增强了开发效率和代码可维护性。
-
功能扩展:新功能或改进功能可通过开发新的插件来实现,无需改动主应用,便于快速迭代和创新。
-
资源优化:按需加载的特性使得应用可以大幅减小初始安装包大小,节约用户设备存储空间。
二:插件化使用演示
新建一个工程plugin-sample1 作为我们的第一个插件工程,代码地址:https://github.com/weiwei0928/plugin_simple_1
如下我们现在版本1的时候打一个包起名plugin_sample_1.apk,在修改为版本2 再打一个包起名plugin_sample1_version2.apk
新建一个工程plugin-host 作为我们的宿主工程,代码地址:https://github.com/weiwei0928/plugin-host,
将上面打好的两个包放到assets目录下,并且添加如下依赖:
// 一个简单,容易理解的插件化框架
implementation 'com.github.weiwei0928:EasyPlugin:1.0.1-beta-0'
最后在applicantion和测试页面添加如下代码:
class TestPluginActivity : AppCompatActivity() {
companion object{
private const val TAG = "TestPluginActivity"
const val PLUGIN_SAMPLE1 = "plugin_sample1" //插件1
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_plugin)
title = "插件测试"
plugin_test.setOnClickListener { startPlugin() }
plugin_update.setOnClickListener { installPlugin("plugin_sample1_version2.apk") }
}
/**
* 启动插件
*
*/
private fun startPlugin() {
PluginManager.loadLastVersionPlugin(PLUGIN_SAMPLE1)
try {
var className = PluginManager.getPlugin(PLUGIN_SAMPLE1).pluginMeta.mainClass
Log.d(TAG, "startPlugin: $className")
val cl: Class<*> = PluginManager.mNowClassLoader.loadClass(className)
val intent = Intent(this, cl)
// startActivity(intent)
PluginManager.startActivity(this, intent)
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
}
/**
* 安装assets中高版本插件plugin_test_version2.apk
* 先拷贝到PluginUtil.getZipPath(PluginConfig.PLUGIN_SAMPLE1)
* 然后调用install()安装。
*
*/
private fun installPlugin(apkName: String) {
val zeusPlugin: ZeusPlugin = PluginManager.getPlugin(PLUGIN_SAMPLE1)
var out: FileOutputStream? = null
var ins: InputStream? = null
try {
val am: AssetManager = PluginManager.mBaseResources.assets
ins = am.open(apkName)
PluginUtil.createDirWithFile(PluginUtil.getZipPath(PLUGIN_SAMPLE1))
out = FileOutputStream(PluginUtil.getZipPath(PLUGIN_SAMPLE1), false)
val temp = ByteArray(2048)
var len: Int
while (ins.read(temp).also { len = it } > 0) {
out?.write(temp, 0, len)
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
PluginUtil.close(ins)
PluginUtil.close(out)
}
val installed: Boolean = zeusPlugin.install()
if (installed) {
Toast.makeText(PluginManager.mBaseContext, "高版本插件安装成功", Toast.LENGTH_SHORT).show()
}
}
}
此时运行我们的plugin-host工程就可以感受插件化应用了!如下gif图