Android模块化框架介绍

模块化是一种成熟的业务解耦思想,目前已广泛应用在APP的开发中。之前写过一篇文章——Android模块化实践对APP模块化的过程及遇到的问题进行了介绍。具体的实例代码最近也完善的差不多了,所以写篇文章介绍一下这个项目——SimpleProject, 一个以分层思想+模块化开发的通用框架,将会被长期维护。

项目结构

本项目是按照Android模块化实践中介绍的结构来开展的,所以可先看下这篇文章了解一下基本结构。项目结构如下所示:

image

其中,MainModule, BaseComponentDemo, BaseLibraryDemo和CommonBusinessDemo都是业务层模块,他们的关系如图所示:

image

MainModule是整个APP的主模块,用来实现APP中主页和路由跳转相关的逻辑,同时也作为Application与其他模块关联的枢纽。

BaseComponentDemo, BaseLibraryDemo和CommonBusinessDemo是子业务模块,都依赖于library目录中的三个公共模块。这三个模块一方面是用来展示业务模块化实现过程,另一方面也是library中三个模块的示例代码。所以这三个模块中没有什么核心的代码,下面主要介绍一下library中的三个模块。

建议

默认情况下,创建的Module都是在Project目录下,但是当模块比较的多的时候,定位代码时还是比较繁琐的,所以推荐将底层的Module放在创建的library目录中,然后在setting.gradle中对Module的路径进行配置:

project(':baselibrary').projectDir = new File('library/baselibrary')
project(':basecomponent').projectDir = new File('library/basecomponent')
project(':commonbusiness').projectDir = new File('library/commonbusiness')

有时候也会引入一些第三方的Module, 此时也可将其放在library目录中,或者创建其他的目录用来存放第三方的Module,然后在setting.gradle中进行配置。这样Project目录下只有业务层的Module,项目结构看起来会清晰很多。

baselibrary

baselibrary是Common组件层的实现,包括各种常用的工具类,通用的UI库,数据源的封装(包括网络,文件,数据库)。

工具类

commonutils中包含了丰富的工具类,具体介绍如下:

AppUtil: App相关的一些操作,如版本号,进程号,是否已安装,是否正在运行,是否运行在前台等;

BitmapUtil: Bitmap相关的一些操作,如缩放,与Drawable之间的转换等;

CollectionUtil: 与集合/数组相关的操作;

ConvertUtil: 基本类型与String之间的转换操作;

DateTimeUtil: 时间格式化相关的操作;

DeviceUtil: 设备相关的操作,如获取系统的各种参数;

EncryptUtil: 加密操作,如MD5, 隐藏手机号,邮箱等操作;

FileUtil: 与文件相关的操作;

InputMethodUtil: 与键盘相关的操作,如打开/隐藏键盘,键盘弹出时调整EditText位置等;

LaunchUtil: 跳转到其他APP的操作,如打开电话,短信等;

LogUtil: 日志工具类;

NetworkUtil: 与网络相关的工具类,如获取网络参数,获取联网状态等;

PermissionUtil: 权限验证类;

RomUtil: 判断手机ROM的类型;

ScrollStateUtil: 判断可滑动View是否到达顶部或底部;

SpannableStringUtil: 富文本工具类;

ToastUtil: Toast工具类

VerificationUtil: 验证工具类,如手机号,邮箱,身份证,是否为中文等;

ViewBgUtil: 动态设置View背景的工具类;

ShadowDrawable: 被View设置阴影的工具类;

数据源

Android中常用的数据源也就四个:SharePreference,文件,数据库和网络。

SharePreference

SharePreference是Android提供的一种以key-value结构用来存储少量数据的方式,本质上也是文件的存储方式,但是直接使用时比较繁琐,为了简化调用过程,项目中提供了它的封装版——PreferencesManager,支持同步和异步两种方式。

文件

文件方式就是简单的文件读写,这里的文件缓存使用了ACache

数据库

与文件一样,数据库也算是Android中的低频数据源,直接使用GreenDAO即可。

网络

网络是Android开发中主要的数据源,会被大量使用,所以需要进行简单的封装,从而简化网络请求的过程。网络框架使用了Retrofit。 http目录中是整个网络框架的封装,其中提供了公共参数,缓存,Cookie,认证四种拦截器。同时提供了Gson数据转换的兼容类,避免异常数据转换时因类型不匹配而导致的闪退。

网络请求示例代码:

HttpManager.getInstance().executeRequest(apiService.getUserInfo(), new ResponseProcessor.RequestListener<UserInfoBean>() {
    @Override
    public void onSuccess(UserInfoBean response) {
        // 请求成功
    }

    @Override
    public void onFailure(int code, String msg) {
        // 请求失败
    }
});

通用UI

通用UI是一些自定义View,放在这个位置的自定义View需要有高度的可定制性和与业务无关的特征。

CircleProgressBar: 圆形进度条;

LevelView: 类似Uber的等级选择器;

RefreshLayout: 下拉刷新、上拉加载组件;

ResilienceListView: 下拉可回弹的ListView;

ShapeImageView: 可定义形状的ImageView;

TabLayout: 类似微信底部的Tab组件;

basecomponent

basecomponent是基础业务层的实现,用于统一APP的代码结构和UI风格。主要包括Activity&Fragment,Dialog的封装。

Activity & Fragment

Activity&Fragment作为Android中承载View的组件,它们的风格基本决定了APP的整体风格。其实就目前主流的设计,Activity/Fragment的UI也就几种状态:

  • 页面加载时是否有加载圈;
  • 页面是否有NavigationBar;

总的来说也就这4种情况的组合。针对这4种情况提供了以下封装类:

  • BaesActivity 不需要网络请求的Activity;
  • BaesProgressActivity 需要网络请求的Activity(页面默认显示加载圈);
  • BaseFragment 不需要网络请求的Fragment;
  • BaseProgressFragment 需要网络请求的Fragment(页面默认显示加载圈);

而对于NavigationBar也提供了三种样式: 白底,透明,半透明,根据需要进行设置即可。

Dialog

Dialog也是Android开发中常用的UI组件,这里提供了普通对话框,单选对话框,多选对话框,底部对话框四种方式,同时对每一种提供了自定义样式和Material样式两种风格,具体可参考Android通用UI组件之Dialog

commonbusiness

commonbusiness是公共组件层的实现。其中包括APP中一些通用的功能,如登录验证,权限验证,第三方登录,分享,支付,推送等功能。

登录验证

在Android开发中,有一些页面是需要登录才能查看的,如果直接使用判断登录状态的方式,就是显得很繁琐。所谓为了简化这种验证过程,项目中提供了基于AOP的方式,开发者中需要验证登录状态的方法上面使用@CheckLogin注解即可。具体代码参考aspect目录。

权限验证

Android6.0之后权限的获取都是通过动态获取的,但是获取的过程比较繁琐,所以为了简化权限的获取过程,这里也使用了基于AOP的权限申请。在需要申请权限时,使用@CheckPermission注解即可,代码如下所示:

@CheckPermission(permissions = {Manifest.permission.CAMERA,}, permissionDesc = "没有权限无法使用相机", settingDesc = "快去设置中开启权限")
private void setUserIcon() {

}

当用户拒绝了权限申请后,弹出toast提示permissionDesc中的内容,当勾选了【不再询问】拒绝后,再次申请就会弹出Dialog, 提示内容为settingDesc,当然,这两个字段也是有默认值的,如果不需要详细的提示,可不用设置。

第三方登录

现在的应用除了内置的登录功能外,为了便于用户使用,通常还会提供第三方登录的功能。通常使用的第三方登录也就微信,微博,QQ三种。这里为第三方登录提供了统一的接口,需要登录时直接调用即可。

分享

目前APP的主要分享渠道是微信,微博和QQ,所以分享模块也只集成了这三种分享方式。使用时只需要在相应的开发平台上创建应用并配置参数,然后在分享模块中配置参数即可。当然,项目中也提供了一个分享页面——ShareActivity,分享时调用ShareActivity.enter(…)方法即可。

支付

项目中集成了微信支付和支付宝支付,并且为支付提供了统一了接口,使用时只需要将从后台获取的参数传入即可

支付宝支付
// requestStr是后台返回的订单相关的参数
PayManager.getInstance(PayActivity.this).payByAliPay(this, requestStr, new PayManager.AliPayListener() {
    @Override
    public void onSuccess() {
        ToastUtil.show("支付成功");
    }

    @Override
    public void onFailure(Exception e) {
        ToastUtil.show("支付失败" + e.getMessage());
    }
});
微信支付
// 根据后台返回的微信支付的参数构造PayRequestBean对象
PayRequestBean payRequest = new PayRequestBean(...)
PayManager.getInstance(PayActivity.this).payByWeChat(payRequest, new PayManager.AliPayListener() {
    @Override
    public void onSuccess() {
        ToastUtil.show("支付成功");
    }

    @Override
    public void onFailure(Exception e) {
        ToastUtil.show("支付失败" + e.getMessage());
    }
});

推送

目前推送的推送率基本都是通过第三方推送SDK组合的方式来保障的,项目中集成了小米,华为,极光推送三种方式,根据机型动态设置推送方式,小米手机使用小米推送,华为推送使用华为推送,其他的品牌则使用极光推送。开发时只需要在Applicataion中调用PushManager的init方法进行初始化,并且设置推送的监听即可。

PushManager.getInstance().initPush(getApplicationContext(), "小米推送的appId",
            "小米推送的appKey");

PushManager.getInstance().setPushListener(new PushListener() {
    @Override
    public void onReceiveMessage(Context context, int pushChannel, Object object) {
        /**
         * 接收到自定义消息时的回调
         */
    }

    @Override
    public void onReceiveNotification(Context context, int pushChannel, Object object) {
        /**
         * 接收到通知时的回调
         */
    }

    @Override
    public void onNotificationClicked(Context context, int pushChannel, Object object) {
        /**
         * 点击推送通知时的回调
         */
    }
});

项目地址

SimpleProject

总结

目前的项目已经有个大概的轮廓了,但是细节方面还有许多需要完善的,同时实例代码的展示也还不够详细,随后会进一步完善,感兴趣的小伙伴可关注。

,