Android应用-开发框架设计

news2024/11/18 8:12:54

目录

1. 📂 简介

1.1 背景

1.2 专业术语

2. 🔱 总体设计思想

2.1 分层:组件化设计框架

2.2 分类:应用开发架构图

3. ⚛️ 框架详细设计

3.1 组件化框架外形

3.2 业务模块化

3.3 代码编程框架

4. 💠 框架其他设计

4.1 版本统一控制

4.2 引入部分第三方框架

4.3 封装网络请求框架

4.4 统一应用签名


1. 📂 简介

1.1 背景

        为减少应用开发重复造轮子,于是希望有一套统一的应用框架,可以让应用开发者快速上手开发需求,而无需过多关注应用框架相关内容。

        而且,基于同一套应用框架,有利于同事互相之间的代码Review与维护,也方便后期项目交接。不仅减少开发人员繁复的工作,而且提升整个团队的产研效率。

1.2 专业术语

术语名称

描述

AndroidStudio

简称AS,是Android开发者用来开发应用的一个工具

Retrofit/okhttp3

知名的网络请求框架

Glide

知名的图片加载框架

LiveEventBus

基于LiveData的应用开发事件总线,方便业务间消息通信,有取代EventBus的趋势

MVVM

基于MVC、MVP的一套代码开发框架

Kotlin

Android开发官方推荐语言

2. 🔱 总体设计思想

2.1 分层:组件化设计框架

        我们知道常见的应用开发框架主要有:模块化、组件化、插件化,那么随着各个应用不断的迭代升级,应用的开发框架也从最开始的单App模块到多模块化,再到组件化与插件化。那么对于一般的应用开发框架,应该遵循什么样的设计原则呢?

        首先,我想到的是不能过度设计,一口不能吃一个大胖子,一来就嚷着要做插件化是不太现实的,框架应该跟随应用需求一步步迭代或重构。其次,直接使用AS创建一个新项目,会缺少应用迭代升级的一些常见元素(如常见的Retrofit、Glide、LiveEventBus等三方开源SDK和一些工具类),在后期慢慢引入时很可能会没有必要的重复踩前人走过的坑。于是,依赖于组件化设计思想——无惧应用后期扩展迭代,再结合应用基本所需元素——搭一个轮子减少重复劳动,就设计出本文将要阐述的应用开发框架,具体思想请继续往下看。

2.2 分类:应用开发架构图

        总体方向是:首先建立一个组件化框架的外形架构,然后实现业务模块化,再搭建一套MVVM+Kotlin代码编程框架。

3. ⚛️ 框架详细设计

3.1 组件化框架外形

        以app模块为总入口,作为组件化中提到的壳工程。app模块不应包含相关业务代码,它的主要工作应该是进行Application初始化、依赖各个模块,和声明各模块manifest相关配置。

3.2 业务模块化

        app模块依赖portal业务模块,暂且我们可将所有业务写在portal模块,后期业务壮大后可朝组件化方向再拆分业务模块。

        middleware模块作为中间件层,放置一些模块间共用的元素,那么项目中除middleware模块之外的其他所有模块,如:app模块和portal模块,都应依赖middleware模块。但需注意,随着业务的增长middleware模块可预料的会不断膨胀,所以写业务时需注意解耦,切勿将非模块间公用的元素放进middleware模块。

        portal模块包括主要的业务代码,采用组件化分包方式搭建各业务模块,比如下面这样的包名结构:

  • com.xxx.xxx.portal.feature.home

  • com.xxx.xxx.portal.feature.bt

  • com.xxx.xxx.portal.feature.wifi

3.3 代码编程框架

        各业务模块采用MVVM框架,包结构为:data-model-view-viewmodel

        使用Kotlin语言,依赖于下沉到middleware模块的BaseActivity、BaseFragment,以及ViewBinding,建立起一套如下的代码编程框架:

4. 💠 框架其他设计

4.1 版本统一控制

        根目录新建version.gradle文件,将各类版本号统一放置此处,在其他gradlle脚本通过 apply from: "${rootDir}/version.gradle" 导入使用。

4.2 引入部分第三方框架

        在middleware模块中引入一些应用开发必要的第三方库,主要包括blankj工具包合集、图片加载框架Glide、网络请求框架和相关配置Retrofit/okhttp3、动效加载工具lottie、以及应用开发事件总线LiveEventBus等。

    api "androidx.constraintlayout:constraintlayout:$CONSTRAINTLAYOUT"
    api "androidx.lifecycle:lifecycle-livedata-ktx:$LIVEDATA"
    api "androidx.lifecycle:lifecycle-viewmodel-ktx:$VIEWMODEL"
    api "androidx.viewpager2:viewpager2:$VIEWPAGER2"
    api "com.blankj:utilcodex:$COM_BLANKJ_UTILCODEX"
    api "com.github.bumptech.glide:glide:$GLIDE"
    api "com.squareup.retrofit2:retrofit:$RETROFIT"
    api "com.squareup.retrofit2:converter-gson:$RETROFIT_CONVERTER_GSON"
    api "com.squareup.retrofit2:adapter-rxjava:$RETROFIT_ADAPTER_RXJAVA"
    api "com.squareup.okhttp3:logging-interceptor:$OKHTTP_LOGGING_INTERCEPTOR"
    api "com.airbnb.android:lottie:$LOTTIE"
    api "io.github.jeremyliao:live-event-bus-x:$LIVE_EVENT_BUS_X"

4.3 封装网络请求框架

        基于Retrofit/okhttp3,封装出相应的ApiFactory以及BaseModel、BaseViewModel,方便基于MVVM项目访问网络,本应用开发框架中已包含整套网络请请求和处理的编程范式,具体可参考如下代码:

Model层:

interface MainApi {

    // 随机获取1张猫图(GET):https://api.thecatapi.com/v1/images/search?limit=1
    @GET("v1/images/search")
    suspend fun getCat(@QueryMap hashMap: HashMap<String, String>): List<CatBean>
//    suspend fun getCat(@QueryMap hashMap: HashMap<String, String>): BaseResponse<CatBean>

}

class MainModel : BaseModel<MainApi>() {

    override fun createApi(): Class<MainApi> = MainApi::class.java

    //    suspend fun getCat(hashMap: HashMap<String, String>): BaseResponse<CatBean> =
    suspend fun getCat(hashMap: HashMap<String, String>): List<CatBean> =
        withContext(Dispatchers.IO) {
            try {
                apiStores.getCat(hashMap)
            } catch (e: Exception) {
                mutableListOf()
            }
        }
}

abstract class BaseModel<T> {

    protected var apiStores: T

    init {
        apiStores = ApiFactory.remoteService(createApi())
    }

    protected abstract fun createApi(): Class<T>

}

网络请求工厂:

object ApiFactory {

    private val okHttpClient: OkHttpClient by lazy { setHttpClient() }

    private fun retrofit(): Retrofit {
        return Retrofit.Builder().baseUrl(Constants.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create()).client(okHttpClient).build()
    }

    private fun setHttpClient(): OkHttpClient = OkHttpClient.Builder().apply {
        addInterceptor(InterceptorManager.headerInterceptor()).addInterceptor(InterceptorManager.httpLoggingInterceptor())
        InterceptorManager.otherInterceptors.forEach { addInterceptor(it) }
    }.connectTimeout(NET_TIMEOUT, TimeUnit.SECONDS).readTimeout(NET_TIMEOUT, TimeUnit.SECONDS)
        .writeTimeout(NET_TIMEOUT, TimeUnit.SECONDS).build()

    @JvmStatic
    fun <T> remoteService(apiService: Class<T>): T {
        return retrofit().create(apiService)
    }

}

 网络请求拦截器:

object InterceptorManager {

    /**
     * 返回头拦截器
     * @return
     */
    fun headerInterceptor(): Interceptor = Interceptor { chain: Interceptor.Chain ->
        chain.proceed(
            chain.request().newBuilder().addHeader(HeaderNames.TOKEN.headerName, "")
                .addHeader(HeaderNames.PLATFORM.headerName, "android")
                .addHeader(HeaderNames.UID.headerName, "")
                .addHeader(HeaderNames.VERSION.headerName, AppUtils.getAppVersionName()).build()
        )
    }

    /**
     * 返回http拦截器
     */
    fun httpLoggingInterceptor(): Interceptor = HttpLoggingInterceptor().apply {
        this.level =
            if (Constants.RELEASE) HttpLoggingInterceptor.Level.NONE else HttpLoggingInterceptor.Level.BODY
    }

    /**
     * 自定义http拦截器
     */
    var otherInterceptors: MutableList<Interceptor> = mutableListOf()

    enum class HeaderNames(val headerName: String) {
        TOKEN("Token"), PLATFORM("Platform"), UID("UID"), VERSION("Version"),
    }

}

4.4 统一应用签名

        在app模块中新增signing.properties文件存储签名信息,xxx.jks签名文件放在同级目录,然后在app模块build.dradle文件中增加如下签名校验信息:

Properties signingProps = new Properties()
signingProps.load(new FileInputStream(file("signing.properties")))

android {
    signingConfigs {
        KeyStore {
            keyAlias signingProps['KEY_STORE_ALIAS']
            keyPassword signingProps['KEY_STORE_KEY_PASSWD']
            storeFile file(signingProps['KEY_STORE_FILE'])
            storePassword signingProps['KEY_STORE_PASSWD']
            v1SigningEnabled true
            v2SigningEnabled true
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            signingConfig signingConfigs.KeyStore
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }

        debug {
            minifyEnabled false
            signingConfig signingConfigs.KeyStore
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/543594.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

streamlit

正常在学习一个新框架之前&#xff0c; 肯定要先调研下这个框架究竟能做些什么事吧&#xff1f; 但对于 streamlit 来说&#xff0c;请你相信我&#xff0c;这是一个你可以无脑去学习的框架&#xff0c;我之所以这么说&#xff0c;是因为我相信终有一天&#xff0c;你一定能用…

【算法学习系列】04 - 由01不等概率随机实现01等概率随机

文章目录 约定条件说明解决方案思路说明实现代码 验证方案 约定条件说明 存在函数 unequalP_01() 不等概率返回 0 和 1。只能通过函数 unequalP_01() 来实现 01 等概率随机函数 equalP_01() 解决方案 为了能够验证最后的等概率随机&#xff0c;这里先把函数 unequalP_01() 实现…

美颜SDK设计思路与架构分析:如何实现高可定制化

当下&#xff0c;美颜SDK也成为了移动应用开发中的必备工具之一。在实际应用中&#xff0c;不同的应用场景需要不同的美颜效果&#xff0c;因此如何实现高可定制化的美颜SDK就成为了一个重要的技术问题。 一、美颜SDK的设计思路 美颜SDK的设计思路需要考虑以下几个方面&…

Vivado 下 AD9767 双通道正弦波产生例程

Vivado 下 AD9767 双通道正弦波产生例程 1、实验简介 本实验基于 Xinlinx 黑金 AX7A035 FPGA 开发板&#xff0c; 练习使用 AN9767 模块&#xff0c;实验中使用的模块是采用 ANALOG DEVICES 公司的 AD9767 芯 片&#xff0c;支持独立双通道、14 位、 125MSPS 的数模转…

金币商城功能迭代. 使用版本号解决数据的并发修改问题

前言. 公司的商城模块嵌在微信公众号里面, 商城里面除了少量的现金业务, 大头在金币业务里面, 商城本来就是用来增加客户粘度的, 金币是客户通过某些行为免费获得如注册, 绑定,推荐等 需求. 金币方面之前的设计: 1.金币只有一个流水表,消费为负,获取为正 2.并且…

github上有什么好的node.js的项目?

前言 可以参考一下下面的nodejs相关的项目&#xff0c;希望对你的学习有所帮助&#xff0c;废话少说&#xff0c;让我们直接进入正题 1、 NodeBB Star: 13.3k 一个基于Node.js的现代化社区论坛软件&#xff0c;具有快速、可扩展、易于使用和灵活的特点。它支持多种数据库&am…

驱动开发:通过应用堆实现多次通信

在前面的文章《驱动开发&#xff1a;运用MDL映射实现多次通信》LyShark教大家使用MDL的方式灵活的实现了内核态多次输出结构体的效果&#xff0c;但是此种方法并不推荐大家使用原因很简单首先内核空间比较宝贵&#xff0c;其次内核里面不能分配太大且每次传出的结构体最大不能超…

jvm之GC

写在前面 本文一起看下GC相关的内容。 1&#xff1a;GC基础内容 1.1&#xff1a;为什么要有GC 内存资源的稀缺性&#xff0c;以及内存管理的复杂性&#xff0c;决定了需要有垃圾回收器这样的角色来帮助我们管理内存资源&#xff0c;避免手动管理带来的内存不能得到正常释放…

普源DS1102Z-E示波器,100MHz带宽

DS1000Z-E系列数字示波器是RIGOL基于主流需求而设计的&#xff0c;电商专供款高性能经济型数字示波器,具备100MHz带宽和1GSa/s采样率&#xff0c;搭载RIGOL独创的UltraVision技术平台&#xff0c;更深的储存&#xff08;标配达24 Mpts&#xff09;&#xff0c;高达30,000 wfms/…

解决基于kvm的win10虚拟机只识别2个cpu的问题

在使用kvmqemu创建win10虚拟机的时候&#xff0c;发现尽管我在virt manager里面指定了72个vcpu&#xff0c;但是win10里面只识别2个cpu核心的现象。 如图所示&#xff1a; 虚拟系统管理器里面当时是这样设置的&#xff1a; 这个时候&#xff0c;对应的xml文件内&#xff0c;关…

【深度学习】离线安装Python及相关第三方库

如果对方电脑无法联网。 那么需要在可以联网的电脑上进行如下操作&#xff0c;随后将整个文件包传输到对方电脑&#xff0c;实现环境配置。 Python 先给离线电脑安装Python初始环境 https://www.python.org/downloads/ 这里我选择下载了Python3.7.8 https://www.python.org…

如何用python在微信公众号上添加自己的ChatGPT

由于之前chatgpt的火热&#xff0c;现在很多微信公众号都接入了chatgpt的接口&#xff0c;来给自家公众号增添一丝乐趣&#xff0c;下面我以自己的经验&#xff0c;用python在微信公众上添加自己的chatGPT&#xff0c;先看下方成果图 三步曲 申请自己的公众号部署服务接入chat…

如何用国产DBDesginer软件进行数据库建模设计?

我们在开发软件系统之前都需要进行数据结构的建模设计&#xff0c;传统的都是通过PowerDesiger等国外的软件或直接Excel来进行数据库表结构设计&#xff0c;今天来了解一下如何使用国产软件来进行数据库建模设计 1、首先是注册DBDesigner用户&#xff08; http://dbdesigner.n…

用蹩脚英语在StackOverflow上飞奔:如何在一个RestApi接口中调用另一个RestApi文件接口发送上传文件请求

上班摸鱼、下班干活&#xff0c;日常埋坑、加班填坑——这是我的搬砖&#xff0c;亦是在座的各位&#xff01; 昨天在StackOverflow上面闲逛&#xff0c;突然看到一个国际友人提出了一个问题&#xff0c;他发出了好久都没有人来回答&#xff0c;本着在下为人处世乐善好施、广结…

视频flv怎么转换成mp4格式?

视频flv怎么转换成mp4格式&#xff1f;关于视频格式转换这个问题&#xff0c;小编发现&#xff0c;就算不是从事视频编辑的朋友也有可能经常会遇到这种转换操作&#xff0c;为什么会这样呢&#xff1f;原因主要是因为视频格式的种类真的非常多&#xff0c;多到我们数不清&#…

软件测试之自动化测试

目录 一、初试自动化测试 1.自动化测试的分类&#xff08;简单了解&#xff09; 2.如何实施自动化单元测试 二、selenium 介绍&#xff08;重点内容&#xff09; 1.工作原理 2.Selenium 环境搭建 2.1 Chrome java 2.2 常见问题及解决方案 1.元素的定位 1.1 CSS 定位…

sonarqube分析仓库

sonarqube可以有多种方式分析仓库 使用GitlabCI 设置项目编码 添加环境变量 创建或修改配置文件 sonarqube-check:image: name: sonarsource/sonar-scanner-cli:latestentrypoint: [""]variables:SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defi…

GE H201Ci-1 单通道变压器控制单元

HYDRAN 201Ci-1一个标准模拟输出通道控制器非隔离&#xff0c;跳线可配置为0-l mA 一个遥控电子控制器或4-20 mA&#xff08;最大输出10 V&#xff09;、0-1 V或0-10 V&#xff1b;0-2000 ppm范围 HYDRANR 201Ti智能变送器&#xff1b;它提供网络通信能力 第二个可选模拟输出加…

基于Web的智慧产业园区3D可视化运营管理平台

改革开放以来&#xff0c;园区逐渐成为地区招商引资、储备人才的重要途径。我国社会、经济处于快速发展阶段&#xff0c;园区正向着智慧化、创、科技化转变。 建设背景 在人类的历史发展过程中&#xff0c;随着5G、人工智能、云计算、物联网、GIS等新一轮信息技术的迅速发展&…

Jenkins流水线整合k8s实现代码自动集成和部署

一、前置条件 1、安装好k8s集群 这里先要搭建好一个K8s集群&#xff0c;笔者这边就采用使用了一个一主一丛的k8s集群&#xff0c;k8s集群的版本使用1.19.5版本&#xff0c;服务器的配置&#xff1a;2核4G&#xff0c;操作系统: CentOS Linux release 7.9.2009 (Core) 主机名…