Android插件化开发之(一)实现

Android插件化开发之(一)实现,第1张

    一、Android插件化开发之(一)实现
    二、Android插件化开发之(二)打包
    三、Android插件化开发之(三)第三方库动态加载
    注:转载请标明出处。

    就目前而言,Android上的插件化开发技术都比较成熟了,很多大厂都有比较稳定的插件开发框架,可以拿来即用,简化开发。对于第三方的这些框架,这里就不多说(作者也不懂^_^),这里我想说的是插件化开发的核心技术,掌握了核心,想开发自己的框架就成为了可能。对于插件的开发,我觉得可以分为三个部分:代理、接口和插件。
一、代理
    代理,我的理解就像是插排的插座,是宿主程序与插件对接的部分。对于这部分该怎么实现,这里就得去了解一下DexClassLoader的用法了,关于DexClassLoader的用法和作用就自己百度吧(人懒!),DexClassLoader是插件化开发的核心中的核心,是我们加载第三方的apk、dex或jar所必须的。我们可以实现一个管理类来 *** 作创建自己的DexClassLoader对象,这个是宿主加载插件用的,怎么实现请看代码:
    private var loader:DexClassLoader ?= null
    {
        var dexPath = "${path}classes2.dex"
        var dex = context.getDir("dex", Context.MODE_PRIVATE)
        loader = DexClassLoader(dexPath, dex.absoluteFile.absolutePath, null,                   context.classLoader)
    }

    fun getDexClassLoader():ClassLoader?{
            return loader
    }
DexClassLoader的构造参数说明:
dexPath:就是你的dex文件或apk文件存放的位置路径。
optimizedDirectory:提取到dex文件后存放文件夹路径,网上有人说无效了(不清楚,没验证),一般按照上面代码中设置值准没错。
libraryPath:so库存放的路径
parent:父classloader
    我这里是以一个BaseActivity作为宿主程序与插件交接的类,首先需要以自己创建的DexClassLoader对象替换了系统的ClassLoader,如下代码:
override fun getClassLoader(): ClassLoader ?{
    return PluginManager.instance.getDexClassLoader()
}
其次获取插件功能的接口对象,代码如下:
    protected var iDeviceInterface :IDeviceInterface  ?= null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        try {
            classLoader?.let {
                val cls = it.loadClass("com.xx.common.BaseDeviceHelper")
                val constructor = cls.getConstructor()
                 val instance = constructor.newInstance()
                 if (instance is IDeviceInterface){
                     iDeviceInterface = instance
                  }
            }
            }catch (e:Exception){
                e.printStackTrace()
            }
    }
通过接口对象,就可以 *** 作插件的内容进行交互了。
二、接口
    接口,这是宿主与插件之间交互的桥梁,这部分可以根据自己的插件需要进行设计就好。这里我将对两种插件做简单的说明。
(1)功能库插件接口
根据自己的功能库设计接口,代码如例:
interface IDeviceInterface {
    fun initDevice():Boolean
    fun releaseDevice():Boolean
}
这里设计了一个第三方库的初始化和释放。
(2)功能块插件接口
定义Activity的基本生命周期接口,根据自己需要定义其他的接口,参考如下:
    interface LifecycleInterface {
        /**
         * 对应setContentView
         */
        fun setPluginContentView(layoutId:Int)
        /**
         * 对应findViewById
         */
        fun  pluginFindViewById(resId:Int) : T
        /**
         * 对应onCreate
         */
        fun onPluginCreate(savedInstanceState:Bundle?)
        /**
         * 对应onSaveInstanceState
         */
        fun onPluginSaveInstanceState(outState:Bundle?)
        /**
         * 注入宿主的上下文
         */
        fun attach(activity: Activity)
        /**
         * 对应onStart
         */
        fun onPluginStart()
        /**
         * 对应onRestart
         */
        fun onPluginRestart()
        /**
         * 对应onResume
         */
        fun onPluginResume()
        /**
         * 对应onPause
         */
        fun onPluginPause()
        /**
         * 对应onStop
         */
        fun onPluginStop()
        /**
         * 对应onDestroy
         */
        fun onPluginDestroy()
    }
三、插件
插件,这是接口的实现部分,所以也分两种类型去考虑,对应接口部分。
(1)功能库插件
定义一个第三方库的管理类,实现对外的接口,代码如下:
    class BaseDeviceHelper:IDeviceInterface {
         override fun initDevice(): Boolean {
             TODO("Not yet implemented")
         }
         override fun releaseDevice(): Boolean {
             TODO("Not yet implemented")
         }
     }
(2)功能块插件
    这类型的插件是把程序中的部分功能模块独立出来实现,相当于将App给拆分出了一部来实现,插件可以独立打包形成新的apk来运行,没有这部分插件也不会影响程序的整体功能运行,这里以一个BaseActivity类来进行代码展示,如下:
abstract class BaseActivity:AppCompatActivity(),LifecycleInterface {
        protected lateinit var activity: Activity
        override fun setPluginContentView(layoutId: Int) {
            if (this::activity.isInitialized) {
                activity.setContentView(layoutId)
            } else super.setContentView(layoutId)
        }
        fun setPluginContentView(layoutView: View) {
            if (this::activity.isInitialized) {
                activity.setContentView(layoutView)
            } else super.setContentView(layoutView)
        }
        override fun  pluginFindViewById(resId: Int): T {
            return if (this::activity.isInitialized)
                activity.findViewById(resId)
            else super.findViewById(resId)
        }
        override fun onPluginCreate(savedInstanceState: Bundle?) {
            if (this::activity.isInitialized) {
            } else super.onCreate(savedInstanceState)
        }
        override fun onPluginSaveInstanceState(outState: Bundle?) {
        }
        override fun attach(activity: Activity) {
            this.activity = activity
        }
        override fun onPluginStart() {
            if (this::activity.isInitialized) {
            } else super.onStart()
        }
        override fun onPluginRestart() {
            if (this::activity.isInitialized) {
            } else super.onRestart()
        }
        override fun onPluginResume() {
            if (this::activity.isInitialized) {
            } else super.onResume()
        }
        override fun onPluginPause() {
            if (this::activity.isInitialized) {
            } else super.onPause()
        }
        override fun onPluginStop() {
            if (this::activity.isInitialized) {
            } else super.onStop()
        }
        override fun onPluginDestroy() {
            if (this::activity.isInitialized) {
            } else super.onDestroy()
        }
        override fun getClassLoader(): ClassLoader {
            return if (this::activity.isInitialized) {
                activity.classLoader
            } else super.getClassLoader()
        }
        override fun getLayoutInflater(): LayoutInflater {
            return if (this::activity.isInitialized) {
                activity.layoutInflater
            } else super.getLayoutInflater()
        }
        override fun getWindowManager(): WindowManager {
            return if (this::activity.isInitialized) {
                activity.windowManager
            } else super.getWindowManager()
        }
        override fun getWindow(): Window {
            return if (this::activity.isInitialized) {
                activity.window
            } else super.getWindow()
        }
    }

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/989759.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存