Android插件化學(xué)習(xí)總結(jié)

插件化概念

個(gè)人總結(jié)為:它是由宿主和插件應(yīng)用結(jié)合而成,兩者遵守一些標(biāo)準(zhǔn)規(guī)范的情況下,插件無需安裝,即可按需加載使用!

插件化優(yōu)點(diǎn)

  • 宿主和插件分開編譯
  • 并發(fā)進(jìn)行開發(fā)
  • 動(dòng)態(tài)更新插件
  • 按需下載模塊
  • 方法數(shù)和變量數(shù) 65536問題

插件化步驟

  • 插件化分為宿主應(yīng)用和插件應(yīng)用
  • 新建Project - 也就是宿主應(yīng)用
  • 新建一個(gè)Module,具有生命周期接口,宿主跳插件應(yīng)用需要遵守一些標(biāo)準(zhǔn)規(guī)范
  • 新建Table Module - 也就是插件應(yīng)用,同時(shí)在BaseActivity里面實(shí)現(xiàn)生命周期接口
  • Module通過attach方法注入上下文context,因?yàn)椴寮pk未安裝,所以不能直接使用插件的上下文
  • 插件里面重寫setContextView(),getWindowManger,getClassLoader這些需要使用上下文的方法,然后使用注入的that進(jìn)行替換super調(diào)用
  • 在宿主app里面創(chuàng)建ProxyActivity,通過插樁的方式進(jìn)行注冊(cè)插件的Activity。ProxyActivity里面獲取跳轉(zhuǎn)傳入的className,同時(shí)重寫getClassLoader和getResource的方法,替換為PluginManager創(chuàng)建的ClassLoader和Resource
  • 創(chuàng)建PluginManager,單例的形式創(chuàng)建,實(shí)現(xiàn)loadPath方法,去加載apk(DexClassLoader)。因?yàn)?未安裝就不能通過getClassLoader的方式Class.forName這樣的方式了
  • 加載未安裝apk(DexClassLoader)
  • 插件二級(jí)Activity的地方回傳到宿主APP里面,BaseActivity里面startActivity

主要代碼有:
1、初始化插件的ClassLoader,插件的主Activity,插件的Resources

object PluginManager {
    private lateinit var dexClassLoader:DexClassLoader
    private lateinit var resource:Resources
    private var entryActivityName:String = ""
    fun loadPath(context:Context,path: String){
        //獲取插件的ClassLoader
        val dexOutFile = context.getDir("dex",Context.MODE_PRIVATE)
        dexClassLoader = DexClassLoader(path,dexOutFile.absolutePath,null,context.classLoader)
        //插件的第一個(gè)Activity
        val packageManager = context.packageManager
        val packageInfo = packageManager.getPackageArchiveInfo(path,PackageManager.GET_ACTIVITIES)
        entryActivityName =  packageInfo.activities[0].name
        //實(shí)例化Resource
        val assetManager = AssetManager::class.java.newInstance()
        AssetManager::class.java.getDeclaredMethod("addAssetPath",String::class.java).invoke(assetManager,path)
        resource = Resources(assetManager,context.resources.displayMetrics,context.resources.configuration)
    }
    fun getClassLoader() = dexClassLoader
    fun getResource() = resource
    fun getEntryActivityName() = entryActivityName
}

2、插樁的形式創(chuàng)建ProxyActivity

class ProxyActivity : Activity() {
    private var className: String? = null
    private var aliPayInterface: IAliPay? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        className = intent.getStringExtra("className")
        try {
            val activityClass = classLoader.loadClass(className)
            val constructor = activityClass.getConstructor(*arrayOf())
            val instance = constructor.newInstance(*arrayOf())
            aliPayInterface = instance as IAliPay
            aliPayInterface!!.attach(this)
            val bundle = Bundle()
            aliPayInterface!!.onCreate(bundle)

        } catch (e: ClassNotFoundException) {
            e.printStackTrace()
        } catch (e: NoSuchMethodException) {
            e.printStackTrace()
        } catch (e: SecurityException) {
            e.printStackTrace()
        } catch (e: InstantiationException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        } catch (e: InvocationTargetException) {
            e.printStackTrace()
        }

    }

    override fun onStart() {
        super.onStart()
        aliPayInterface!!.onStart()
    }

    override fun onResume() {
        super.onResume()
        aliPayInterface!!.onResume()
    }

    override fun onPause() {
        super.onPause()
        aliPayInterface!!.onPause()
    }

    override fun onStop() {
        super.onStop()
        aliPayInterface!!.onStop()
    }

    override fun onDestroy() {
        super.onDestroy()
        aliPayInterface!!.onDestroy()
    }

    override fun getClassLoader(): ClassLoader {
        return PluginManager.getClassLoader()
    }

    override fun getResources(): Resources {
        return PluginManager.getResource()
    }

    override fun startActivity(intent: Intent) {
        val classNameFromTaoPiaoPiao = intent.getStringExtra("className")
        val newIntent = Intent(this, ProxyActivity::class.java)
        newIntent.putExtra("className", classNameFromTaoPiaoPiao)
        startActivity(newIntent)
    }
}

通過插件的classLoader和傳入的className獲取到約定規(guī)范的AliPay接口,然后調(diào)用插件里面主Activity的生命周期,同時(shí)重寫ProxyActivity的跳轉(zhuǎn),從而實(shí)現(xiàn)插件的二級(jí)頁面的跳轉(zhuǎn)。

詳細(xì)Demo查看Github-GoachAlipay

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容