企业在数字化转型中如何利用常用前端框架提高开发效率并确保安全合规?
755
2022-10-12
BaseProject是一个Android基础程序架构库的一些库
README
BaseProject
For the English readme:English
Android项目基础库,包含四大部分: 一、分辨率适配 二、网络请求框架Retrofit2封装 三、Android基类封装和项目常用Utils方法 四、基于RxJava、RxAndroid的事件总线RxBus。
Android分辨率适配方案,解决大家的分辨率适配烦恼,可以直接依据设计图写尺寸,不做额外的操作,简单方便准确。封装Retrofit2,统一了异常处理,对网络错误,网络错误,连接失败,证书验证失败进行了统一封装,无需用户在单独处理,框架已经做了统一处理,只需在处理正确返回部分。对服务器定义的Api错误,也做了处理,未来完善可以让用户自定义服务器返回错误,和自定义服务器返回数据类型,现在还需要遵循统一格式。封装android开发中常用的Utils,也许你的项目只需要这一个库就完全够了。不信你看,有图有真相。高仿iOS进度条和对话框、activity基类的封装(可继承自BaseActivity自行拓展)、常用自定义View(圆角头像等)、Glide一行代码加载图片、可直接依赖使用。在Rxjava、RxAndroid基础上进行了封装,并对Android进行了优化的事件总线RxBus。事件总线就是一条通信用的通道,上面跑着各种信息,Android中的各个组件或是控件都可以向它发送各种信息,在各个组件或控件中只要订阅这条总线,每当总线收到消息的时候,这些订阅者同样就能收到这些消息。减少广播等高占用资源控件的使用。 喜欢的话不妨star一下吧。
Author陈刚 sam QQ:356576318 QQ群:688700847
E-mail:356576318@qq.com
目录
屏幕分辨率适配Retrofit2封装RxBus集成常用Utils封装集成该库
一、屏幕分辨率适配
分辨率适配概述
采用了2种屏幕适配方式,用户可以自己的需要进行选择。1、头条屏幕适配方式;2、Dimens适配方式
1、头条屏幕适配方案
基本原理
方案的原理其实很简单,首先我们要明白一点,无论我们在xml中使用何种尺寸单位(dp、sp、pt……),最后在绘制时都会给我们转成px!知道这点后,剩下的容易了,我们选定一种尺寸单位 (dp、sp、pt ……)作为我们的适配单位,然后篡改这个单位与px之间的转化比例,然后在xml中使用选定的单位做适配!就是这么简单。我这里是采用自定义的px,和sp,这样更灵活。方便切换 不同适配方案的时候,不用改动任何的布局代码。今日头条屏幕适配方案的核心原理在于,根据以下公式算出 density 当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density density 的意思就是 1 dp 占当前设备多少像素。在屏幕适配中,我们一般只对宽度适配,毕竟高度可以滑动解决!而且高度值,标准屏,虚拟键、全面屏等五花八门,手机的宽高比许多厂家也不一样。 这个方案的思路,主旨是通过修改density值,强行把所有不同尺寸分辨率的手机的宽度dp值改成一个统一的值,这样就解决了所有的适配问题。比如,设计稿宽度是360px,那么开发这边就会把 目标dp值设为360dp,在不同的设备中,动态修改density值,从而保证(手机像素宽度)px/density这个值始终是360dp,这样的话,就能保证UI在不同的设备上表现一致了。 该方案有如下几点优势:
a、侵入性很低,而且也没有涉及私有API
b、今日头条的大厂在用,稳定性有保证的
c、不会有任何性能的损耗
d、使用成本低,使用该方案后在页面布局时不需要额外的代码和操作
e、可适配三方库的控件和系统的控件(不止是 Activity 和 Fragment,Dialog、Toast 等所有系统控件都可以适配),由于修改的 density 在整个项目中是全局的,所以只要一次修改,项目中的所有地方都会受益。
如果是新项目采用基本没有缺点。
项目引入方法
1.引导页Activity继承BaseScreenAdaptActivity,重新相关方法
@Override protected void initScreenAdaption() { if (ScreenUtils.isPortrait()) { ScreenUtils.adaptScreen4VerticalSlide(this, AppConfig.widthInPx); } else { ScreenUtils.adaptScreen4HorizontalSlide(this, AppConfig.heightInPx); } }
2.AppConfig里面配置widthInPx,heightInPx为相应的效果图像素宽度值,如果横屏就是高度值
3.布局中使用方法。拿到效果图,不需要额外计算,布局直接抄设计图上的尺寸。你说爽不爽。布局文件里面的xml使用方式同屏幕适配的第二种适配方法,请在后面查看
2、Dimens屏幕适配方案
该方案参考的了Android适配领域做得比较好的方案,如郭霖,Stormzhang,鸿洋和凯子的方案,可以说综合了各家之所长。 以最小的代价,实现最好的适配效果。我们都希望分辨率适配是这样。拿到效果图,不需要额外计算,布局直接抄设计图上的尺寸。 我的适配方案就可以达到这样的效果,你说爽不爽。
基本原理
App在运行的时候,会在Res下读取对应的dimens文件,BaseProject已经在Res里面对主流的手机的常用分辨率建立的所有的对应关系, 无需用户额外操作,就可以完美适配主流手机。亲测可以适配市面主流手机的95%,即使默认不能适配的手机,也可以通过本文的工具进行适配(ResolutionTools.jar)。用户如果想适配其他分辨率,也提供了相应的获取方法。 介于低于1280x720的低端手机已经很少,所有960x640,480x320等低分辨率手机没有提供默认支持,如需支持,请手动添加。
默认支持的分辨率
分辨率 | 分辨率描述 |
---|---|
1280 x 720 | 无虚拟键1280x702手机 |
1184 x 720 | 带虚拟键1280x720手机实际dimens夹 |
xhdpi | 手机密度为xhdpi的其他型号手机 |
1920 x 1080 | 无虚拟键盘1920x1280手机,常见型号小米,OPPO,vivo,联想,中兴,魅族等手机 |
1776 x 1080 | 带虚拟键盘1920x1280手机,常见型号Google nexus5 |
1794 x 1080 | 带虚拟键盘1920x1280手机,常见型号oppo,vivio华为等手机型号 |
1812 x 1080 | 带虚拟键盘1920x1280手机,常见型号小米,华为等手机型号 |
2220 x 1080 | 渲染分辨率为2220x1080,物理分辨率2960x1440,常见型号三星S8(可以在设计里面进行分辨率的设置) |
2280 x 1080 | 常见型号华为p20,屏幕比例19:9 |
xxhdpi | 手机密度为xxhdpi的其他型号手机 |
2560 x 1440 | 无虚拟键盘2560x1440手机,常见型号小米,OPPO,vivo,联想,中兴,魅族等手机 |
2392 x 1440 | 带虚拟键盘2560x1440手机,常见型号Google pixsel系列 |
2712 x 1440 | 密度3.5,分辨率2560x1440手机,常见型号Google nexus6等 |
2792 x 1440 | 常见型号三星S8+等,dimens实际文件夹 |
2960 x 1440 | 常见型号三星s9等,dimens实际文件夹 长宽比18.5:9 |
xxxhdpi | 手机密度为xxxhdpi的其他型号手机 |
集成分辨率适配
使用概述
有两种集成分辨率适配的方式。
1.-demo工程,doc-res文件夹-values全部拷贝到自己的工程
其他分辨率通过doc/工具集/分配率适配dimens工具.jar手动添加
加需要额外支持的dimens拷贝到自己的工程res下,注意输入的名字是values+xxxdpi+分辨率的形式,如values-xhdpi-960x640
分辨率适配工具-:
https://github.com/fly803/BaseProject/blob/master/doc/Tools/ResolutionAdaption.jar
2.通过BaseProject提供的工具手动集成,利用工具生成dimens,将所有的dimens和相应的文件夹拷贝到自己工程的res文件夹
分辨率适配工具-:
https://github.com/fly803/BaseProject/blob/master/doc/Tools/ResolutionAdaption.jar
布局中的具体使用方法,2种适配方法,布局layout写法一致:
按照我们的思想:
布局直接抄设计图上的尺寸
布局文库应该这么写:
来张组合图,直接根据效果图输入相应的尺寸,只是写法上,如果是1px,改成px1就可以了,字体如果是1sp,改成sp1就可以了,感受一下:
感受完了,想一想,按照这种方式去写布局你说爽不爽。
首先说一下:这个px1并不代表写死1px像素,我在内部会进行dp处理,转成相应手机对应的尺寸。字体单位sp1也在内部进行相应的到安卓sp的转换。这就是本库适配的原理。
接下来:看下不同手机,不同分辨率下的效果:
上述若干不同分辨率的手机,完美实现了适配,最为重要的是:
再也不用拿着设计稿去想这控件的宽高到底取多少dp再也不用去计算百分比了(如果使用百分比控件完成适配)再也不用去跟UI MM去解释什么是dp了
而且细心的同学肯定发现,最底下有3条横向的细线很奇怪,效果图怎么会出这种图。其实那3条横线只是为了说明适配效果,我特意加上去的。现在效果图的尺寸是 1920x1080,现在照抄宽度px1080,和宽度的一半px540.大家可以看到多款手机型号和分辨率不同,但是宽度条正好充满了全部和充满了一半,证明适配效果良好。
二、网络请求框架Retrofit2封装
1.Retrofit+RxJava 优雅的处理服务器返回异常、错误
异常&错误
实际开发经常有这种情况,比如登录请求,接口返回的 信息包括请求返回的状态:失败还是成功,错误码,User对象等等。如果网络等原因引起的登录失败可以归结为异常,如果是用户信息输入错误导致的登录失败算是错误。
假如服务器返回的是统一数据格式:
/** * 标准数据格式 * @param
网络异常导致的登录失败,在使用Retrofit+RxJava请求时都会直接调用subscribe的onError事件;密码错误导致的登录失败,在使用Retrofit+RxJava请求时都会调用subscribe的onNext事件;
无论是异常还是错误,都要在subscribe里面处理异常信息,如下代码:
APIWrapper.getInstance().login("username", "password") .subscribe(new Observer
现在我希望在发生任何错误的情况下,都会调用onError事件,并且由model来处理错误信息。那么,此时我们就应该有一个ExceptionEngine来处理事件流中的错误信息了。 在工作流中处理异常
在正常情况下,我们获取网络数据的流程通常如下:
请求接口->解析数据->更新UI
整个数据请求过程都是发生在Rx中的工作流之中。当有异常产生的时候,我们要尽量不在ui层里面进行判断,换句话说,我们没有必要去告诉ui层具体的错误信息,只需要让他弹出一个信息(Toast或者Dialog)展示我们给它的信息就行。
统一封装,拦截异常错误
统一封装拦截异常错误主要是为了获取具体的错误信息,分发给上层的UI,给用户以提示,增强用户体验。
/** * 所以调研接口,统一调用这个方法 * @param ob * @param subscriber */ public void toSubscribe(Observable ob, final ProgressSubscriber subscriber) { //数据预处理 ObservableTransformer
2.集成Retrofit封装使用方法
进行如上操作好,就可以调用相应的接口了,调用方式如下所示。
RequestBusiness.getInstance().toSubscribe(RequestBusiness.getInstance().getAPI().rxGet("220.181.90.8"), new ProgressSubscriber
由于统一对异常和错误进行了封装,所以只写onNext方法就可以了。
三、Android基类封装和常用Utils方法
1.Android常用工具栏
工具 | 描述 |
---|---|
ActivityUtils | Activity管理工具类 |
AppUtils | Adb工具类 |
AndroidSystemUtils | Android系统工具类 |
AnimationUtils | 动画工具类 |
AppUtils | App工具类 |
AssetsUtils | 获取Assets资源 |
BitmapUtils | BitmapUtils工具类 |
CameraUtils | 调用相机工具类 |
ConvertUtils | 转换工具类 |
DateUtils | Date工具类 |
EasyPermissionUtil | 权限操作工具类 |
FileUtils | 文件帮助类 |
IDCardUtil | 身份证工具类 |
DeviceStatusUtils | 手机状态工具类 主要包括网络、蓝牙、屏幕亮度、飞行模式、音量等 |
JsonUtils | JsonUtils |
KeyBoardUtils | 键盘操作 |
NetworkUtilsNetworkUtils | 判断网络连接工具类 |
NioFileUtiles | NioFileUtiles |
NullUtils | NullUtils |
PicassoUtils | PicassoUtils |
RadixCoversion | 进制转换 |
ResolutionAdaptationUtils | 分辨率适配工具类 |
ResourceUtils | 资源操作工具类 |
SdCardUtils | SdCardUtils工具类 |
SettingUtils | SettingUtils |
SharedPreferencesUtils | SharedPreferencesUtils |
SpannableStringUtils | 设置文字工具类 |
StringUtils | StringUtils |
TintUtils | Drawable 着色工具类 |
ToastUtils | ToastUtils |
URLUtils | URLUtils |
ValidateUtils | 验证工具类 |
ZipUtils | ZipUtils |
基类封装
使用请参考demo,请继承自BaseActivity自行拓展
public abstract class BaseActivity extends AppCompatActivity { protected BaseActivity mContext; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (isTranslucentStatus()!=0) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { setTranslucentStatus(true); SystemBarTintManager tintManager = new SystemBarTintManager(this); tintManager.setStatusBarTintEnabled(true); tintManager.setStatusBarTintResource(isTranslucentStatus());//通知栏所需颜色 } } Bundle extras = getIntent().getExtras(); if (null != extras) { getBundleExtras(extras); } mContext = this; setContentView(getLayoutId()); ButterKnife.bind(this); AppManager.getAppManager().addActivity(this); initView(savedInstanceState); initData(); } /** * 是否需要沉浸式状态栏 不需要时返回0 需要时返回颜色 * * @return StatusBarTintModle(boolean isTranslucentStatus, int color); */ protected abstract @ColorRes int isTranslucentStatus(); /** * 设置布局ID * * @return 资源文件ID */ protected abstract @LayoutRes int getLayoutId(); /** * 初始化View * * @param savedInstanceState aty销毁时保存的临时参数 */ protected abstract void initView(Bundle savedInstanceState); /** * 初始化数据源 */ protected abstract void initData(); /** * Bundle 传递数据 * * @param extras */ protected abstract void getBundleExtras(Bundle extras); @TargetApi(19) private void setTranslucentStatus(boolean on) { Window win = getWindow(); WindowManager.LayoutParams winParams = win.getAttributes(); final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; if (on) { winParams.flags |= bits; } else { winParams.flags &= ~bits; } win.setAttributes(winParams); } //Toast显示 protected void showToast(String string) { DialogUIUtils.showToast(string); } @Override protected void onDestroy() { super.onDestroy(); ButterKnife.unbind(this); AppManager.getAppManager().finishActivity(this); } /** * 界面跳转 * * @param cls 目标Activity */ protected void readyGo(Class> cls) { readyGo(cls, null); } /** * 跳转界面,传参 * * @param cls 目标Activity * @param bundle 数据 */ protected void readyGo(Class> cls, Bundle bundle) { Intent intent = new Intent(this, cls); if (null != bundle) intent.putExtras(bundle); startActivity(intent); } /** * 跳转界面并关闭当前界面 * * @param cls 目标Activity */ protected void readyGoThenKill(Class> cls) { readyGoThenKill(cls, null); } /** * @param cls 目标Activity * @param bundle 数据 */ protected void readyGoThenKill(Class> cls, Bundle bundle) { readyGo(cls, bundle); finish(); } /** * startActivityForResult * * @param cls 目标Activity * @param requestCode 发送判断值 */ protected void readyGoForResult(Class> cls, int requestCode) { Intent intent = new Intent(this, cls); startActivityForResult(intent, requestCode); } /** * startActivityForResult with bundle * * @param cls 目标Activity * @param requestCode 发送判断值 * @param bundle 数据 */ protected void readyGoForResult(Class> cls, int requestCode, Bundle bundle) { Intent intent = new Intent(this, cls); if (null != bundle) { intent.putExtras(bundle); } startActivityForResult(intent, requestCode); }}
四、事件总线RxBus
使用方法
我们推荐获取一个RxBus的单例:
Bus bus = BusProvider.getInstance();
订阅Subscribing
@Subscribepublic void onEvent(SomeEvent event) { // TODO: Do something}
你应该也创建订阅像下面这样:
CustomSubscriber
注册和注销你的观察者,为了收到事件,一个类实例应该注册使用RxBus
bus.register(this);
这定制的订阅器也需要注册使用RxBus bus.registerSubscriber(this, customSubscriber);
请也记得注销RxBus当适当的时候 bus.unregister(this);
发布事件
为了发布一个事件,调用post方法 bus.post(new SomeEvent("Message"));
集成该库
1.通过jitpack.io仓库方式依赖
项目根目录下的build.gradle 中加入
allprojects { repositories { maven { url "https://jitpack.io" }//加入这一行代码 } }
在APP的build.gradle dependencies节点下加入
implementation 'com.github.fly803:BaseProject:相应的版本号:例如1.0.0' 配置仓库,添加mavenCentral() maven { url 'https://jitpack.io' }
当前可以-版本
implementation 'com.github.fly803:BaseProject:1.0.0',已release里面的最新release为准
2.clone项目到本地,将BaseProject库直接依赖到项目。
compile project(':BaseProject')
3.aar方式依赖
在项目根目录下新建aars文件夹,将BaseProject目录build/outputs下的kutils-release.aar文件copy进aars文件夹 在app的build.gradle 最外层节点加入
repositories { flatDir { dirs '../aars' } }
在dependencies节点下加入对aar的依赖
compile(name: 'BaseProject-release', ext: 'aar')
项目地址:https://github.com/fly803/BaseProject 集成过程出现问题可联系本人QQ:356576318(注明来自github)
English | 中文
友情链接
github/UCodeUStory/S-MVP
github/UCodeUStory/GradlePluginDevelop
License
Copyright 2015 bingoogolappleLicensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License at http://apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.Project location:https://github.com/fly803/BaseProject
点我回到顶部
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~