Jetpack Compose 中的动态加载、插件化技术探索

这篇具有很好参考价值的文章主要介绍了Jetpack Compose 中的动态加载、插件化技术探索。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在传统的 Android 开发模式中,由于界面过分依赖于 ActivityFragment这样的组件,一个业务模块中往往会存在着大量的 Activity 类,因此诞生了很多的插件化框架,这些插件化框架基本都是想方设法的使用各种Hook/反射手段来解决使用未注册的组件问题。在进入 Jetpack Compose 的世界以后,Activity 的角色被淡化了,由于一个 Composable 组件就可以承担一个屏幕级的显示,因此我们的应用中不再需要那么多的 Activity 类,只要你喜欢,你甚至可以打造一个单 Activity 的纯 Compose 应用。

本文主要尝试探索几种可以在 Jetpack Compose 中实施插件化/动态加载的可行性方案。

以 Activity占坑的方式访问插件中的 Composable 组件

这种方式其实传统 View 开发也可以做,但是由于 Compose 中我们可以只使用一个Activity,而其余页面均使用 Composable 组件来实现,感觉更加适合它。因此主要的思路就是在宿主应用的 AndroidManifest.xml 中注册一个占坑的 Activity类,该 Activity实际存在于插件中,然后在宿主中加载插件中该 Activity的Class,启动插件中的该Activity并传递不同的参数,以显示不同的 Composable 组件。说白了就是借助一个空壳 Activity 来做跳板去展示不同的 Composable 。

首先在工程中新建一个 module 模块,将 build.gradle 中的 'com.android.library' plugins配置改为 'com.android.application',因为这个模块是当成一个 application 模块开发的,最终以 apk 的形式提供插件。然后在其中新建一个 PluginActivity 作为跳板 Activity,并新建两个测试的 Composable 页面。

Jetpack Compose 中的动态加载、插件化技术探索,Jetpack Compose,android,Jetpack Compose,插件化,动态加载,远程加载

PluginActivity 的内容如下:

class PluginActivity: ComponentActivity() {
   
    override fun onCreate(savedInstanceState: Bundle?) {
   
        super.onCreate(savedInstanceState)
        val type = intent.getStringExtra("type") ?: "NewsList"
        setContent {
   
            MaterialTheme {
   
                if (type == "NewsList") {
   
                    NewsList()
                } else if (type == "NewsDetail") {
   
                    NewsDetail()
                }
            }
        }
    }
}

这里就是简单的根据 intent 读取的 type 类型来判断,如果是 NewsList 就显示一个新闻列表的 Composable 页面, 如果是 NewsDetail 就显示一个新闻详情的 Composable 页面。

NewsList 内容如下:

@Composable
fun NewsList() {
   
    LazyColumn(
        Modifier.fillMaxSize().background(Color.Gray),
        contentPadding = PaddingValues(15.dp),
        verticalArrangement = Arrangement.spacedBy(10.dp)
    ) {
   
        items(50) {
    index ->
            NewsItem("我是第 $index 条新闻")
        }
    }
}

@Composable
private fun NewsItem(
    text : String,
    modifier: Modifier = Modifier,
    bgColor: Color = Color.White,
    fontColor: Color = Color.Black,
) {
   
    Card(
        elevation = 8.dp,
        modifier = modifier.fillMaxWidth(),
        backgroundColor = bgColor
    ) {
   
        Box(
            Modifier.fillMaxWidth().padding(15.dp),
            contentAlignment = Alignment.Center
        ) {
   
            Text(text = text, fontSize = 20.sp, color = fontColor)
        }
    }
}

NewsDetail 内容如下:

@Composable
fun NewsDetail() {
   
    Column {
   
        Text(text = "我是插件中的新闻详情页面".repeat(100))
    }
}

执行 assembleDebug,将生成的 apk 文件拷贝到宿主 app 模块的 assets 目录下,以便在应用启动后从其中拷贝到存储卡(实际项目中应当从服务器下载)。

Jetpack Compose 中的动态加载、插件化技术探索,Jetpack Compose,android,Jetpack Compose,插件化,动态加载,远程加载

然后在宿主app模块的 AndroidManifest.xml 中注册插件中定义的 PluginActivity 进行占坑,这里爆红也没有关系,不会影响打包。

Jetpack Compose 中的动态加载、插件化技术探索,Jetpack Compose,android,Jetpack Compose,插件化,动态加载,远程加载

然后在app模块中定义一个 PluginManager 类,主要负责加载插件中的 Class文章来源地址https://www.toymoban.com/news/detail-625027.html

import android.annotation.SuppressLint
import android.content.Context
import dalvik.system.DexClassLoader
import java.io.File
import java.lang.reflect.Array.newInstance
import java.lang.reflect.Field

class PluginManager private constructor() {
   

    companion object {
   

        var pluginClassLoader : DexClassLoader? = null

        fun loadPlugin(context: Context) {
   
            val inputStream = context.assets.open("news_lib.apk")
            val filesDir = context.externalCacheDir
            val apkFile = File(filesDir?.absolutePath, "news_lib.apk")
            apkFile.writeBytes(inputStream.readBytes())

            val dexFile = File(filesDir, "dex")
            if (!dexFile.exists()) dexFile.mkdirs()
            println("输出dex路径: $dexFile")
            pluginClassLoader = DexClassLoader(apkFile.absolutePath, dexFile.absolutePath, null, this.javaClass.classLoader)
        }

        fun loadClass(className: String): Class<*>? {
   
            try {
   
                if (pluginClassLoader == null) {
   
                    println("pluginClassLoader is null")
                }
                return pluginClassLoader?.loadClass(className)
            } catch (e: ClassNotFoundException) {
   
                println("loadClass ClassNotFoundException: $className")
            }
            return null
        }

        /**
         * 合并DexElement数组: 宿主新dexElements = 宿主原始dexElements + 插件dexElements
         * 1、创建插件的 DexClassLoader 类加载器,然后通过反射获取插件的 dexElements 值。
         * 2、获取宿主的 PathClassLoader 类加载器,然后通过反射获取宿主的 dexElements 值。
         * 3、合并宿主的 dexElements 与 插件的 dexElements,生成新的 Element[]。
         * 4、最后通过反射将新的 Element[] 赋值给宿主的 dexElements。
         */

到了这里,关于Jetpack Compose 中的动态加载、插件化技术探索的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android Jetpack Compose 别裁

    一、简介 二、compose优缺点 三、compose好学吗 四、Android Jetpack Compose 跟 fluter 哪个更好 五、Android Jetpack Compose 跟 fluter 技能学习选择 之所以叫Android Jetpack Compose别裁是希望能取舍网上的对compose的资料,推出别出心裁的文章,文章结束都会有一个案例,通过实践学习,让学习的

    2024年02月03日
    浏览(46)
  • Jetpack Compose: Hello Android

    Jetpack Compose 是一个现代化的工具包,用于使用声明式方法构建原生 Android UI。在本博文中,我们将深入了解一个基本的 “Hello Android” 示例,以帮助您开始使用 Jetpack Compose。我们将探讨所提供代码片段中使用的函数和注解。 在深入代码之前,请确保您已经准备好使用 Jetpac

    2024年03月10日
    浏览(43)
  • Jetpack Compose中的动画

    Jetpack Compose中没有沿用Android原有的View动画和属性动画,而是新创建了一套全新的动画系统API,这是理所当然的,因为旧的动画系统主要是基于View体系的,而Compose中需要针对的是Composable可组合函数进行处理,那么势必要创造一套新的玩具出来,同时,这也无疑增加了开发者

    2024年02月08日
    浏览(31)
  • Jetpack Compose中的Accompanist

    accompanist是Jetpack Compose官方提供的一个辅助工具库,以提供那些在Jetpack Compose sdk中目前还没有的功能API。 权限 依赖配置: 单个权限申请 例如,我们需要获取相机权限,可以通过 rememberPermissionState(Manifest.permission.CAMERA) 创建一个 PermissionState 对象,然后通过 PermissionState.statu

    2024年02月03日
    浏览(26)
  • Android Jetpack Compose — Slider滑动条

            在Android Jetpack Compose中,Slider(滑动条)是一个常用的用户界面控件,它允许通过滑动条来选择一个范围或数值。Slider控件非常适用于调整音量、亮度、进度等需要连续调整的场景。 一、Slider的属性         Slider是Android Jetpack Compose中的一个控件,用于实现滑动条

    2024年02月11日
    浏览(31)
  • Android Jetpack Compose之RadioGroup的使用

    Android Jetpack Compose是一个现代化的UI工具包,帮助开发者以声明式的方式构建出美观且功能强大的Android应用。在本文中,我们将详细介绍其中的一个重要组件—— RadioGroup 。 一. RadioGroup简介 Jetpack Compose中并没有像传统View系统中那样直接提供 RadioGroup ,但我们可以很方便地通

    2024年02月06日
    浏览(40)
  • Jetpack Compose中的副作用

    从本质上讲,副作用是任何超出函数控制和作用域的东西。副作用会使函数变得不确定,因此它们使开发人员难以推理代码。 想象有一个函数,它被期望对两个数相加: 对于相同的输入值,其结果永远不会变化,也就是说,不会因为运行次数的增加导致输出结果的不同,因

    2024年02月03日
    浏览(28)
  • 现代化 Android 开发:Jetpack Compose 最佳实践

    作者:古哥E下 如果一直关注 Compose 的发展的话,可以明显感受到 2022 年和 2023 年的 Compose 使用讨论的声音已经完全不一样了, 2022 年还多是观望,2023 年就有很多团队开始采纳 Compose 来进行开发了。不过也有很多同学接触了下 Compose,然后就放弃了。要么使用起来贼特么不顺手

    2024年02月17日
    浏览(48)
  • Android Jetpack Compose中使用字段验证的方法

    数据验证是创建健壮且用户友好的Android应用程序的关键部分。随着现代UI工具包Jetpack Compose的引入,处理字段验证变得更加高效和直观。在这篇文章中,我们将探讨如何在Android应用中使用Jetpack Compose进行字段验证。 字段验证是确保用户在各种输入字段中输入的数据符合特定

    2024年02月11日
    浏览(32)
  • Android Jetpack Compose实现轮播图效果

    在最近思索如何使用Compose方式改进我的开源TMDB电影列表应用程序的主屏幕时,一个激动人心的概念浮现在我的脑海中——为什么不整合一个吸引人的轮播图来展示即将上映的电影呢?在本文中,我将分享我的开发和实现自定义轮播图的经历,提供涉及不同步骤的见解。 首先

    2024年02月08日
    浏览(82)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包