SkillAgentSearch skills...

BaseProject

BaseProject 是一个Android基础程序架构库(安卓屏幕适配ResolutionAdaption,安卓分辨率适配,android各版本分辨率适配,网络通信,公用方法等, Android开发基础库 ,Android基础框架库,作为Android架构非常实用),使用它可以快速稳定高效的建立一个Android工程, 它集成了一个项目最基本,可以说每个项目必备的一些库。 省的自己导入BaseActivity,BaseFragment,集成好分辨率适配(屏幕适配),使开发者可以 用侵入性最小的代价完成Android屏幕适配(安卓分辨率适配),网络请求(RxJava2+Retrofit2), 有大量常用的工具类。让你更加专注去实现自己产品需求, 业务逻辑,而不是浪费时间在重复的工作上!,包含四大部分:一、分辨率适配 二、网络请求框架Retrofit2封装 三、Android基类封装和项目常用Utils 方法 四、基于RxJava、RxAndroid的事件总线RxBus。 For the English readme:## [English](https://github.com/fly803/BaseProject/README_EN.md) |

Install / Use

/learn @fly803/BaseProject
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

README

BaseProject

For the English readme:English

Android项目基础库,包含四大部分:
一、分辨率适配
二、网络请求框架Retrofit2封装
三、Android基类封装和项目常用Utils方法
四、基于RxJava、RxAndroid的事件总线RxBus。

  1. Android分辨率适配方案,解决大家的分辨率适配烦恼,可以直接依据设计图写尺寸,不做额外的操作,简单方便准确,android各版本分辨率适配。
  2. 封装Retrofit2,统一了异常处理,对网络错误,网络错误,连接失败,证书验证失败进行了统一封装,无需用户在单独处理,框架已经做了统一处理,只需在处理正确返回部分。对服务器定义的Api错误,也做了处理,未来完善可以让用户自定义服务器返回错误,和自定义服务器返回数据类型,现在还需要遵循统一格式。
  3. 封装android开发中常用的Utils,也许你的项目只需要这一个库就完全够了。不信你看,有图有真相。高仿iOS进度条和对话框、activity基类的封装(可继承自BaseActivity自行拓展)、常用自定义View(圆角头像等)、Glide一行代码加载图片、可直接依赖使用。
  4. 在Rxjava、RxAndroid基础上进行了封装,并对Android进行了优化的事件总线RxBus。事件总线就是一条通信用的通道,上面跑着各种信息,Android中的各个组件或是控件都可以向它发送各种信息,在各个组件或控件中只要订阅这条总线,每当总线收到消息的时候,这些订阅者同样就能收到这些消息。减少广播等高占用资源控件的使用。
    喜欢的话不妨star一下吧。


Author陈刚 sam QQ:356576318 QQ群:688700847

E-mail:356576318@qq.com


目录

一、屏幕分辨率适配

分辨率适配概述

采用了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手动添加

log

加需要额外支持的dimens拷贝到自己的工程res下,注意输入的名字是values+xxxdpi+分辨率的形式,如values-xhdpi-960x640

log log

分辨率适配工具下载地址:

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写法一致:

拿到效果图: log

按照我们的思想:
布局直接抄设计图上的尺寸
布局文库应该这么写:

log

来张组合图,直接根据效果图输入相应的尺寸,只是写法上,如果是1px,改成px1就可以了,字体如果是1sp,改成sp1就可以了,感受一下:

log

感受完了,想一想,按照这种方式去写布局你说爽不爽。
首先说一下:这个px1并不代表写死1px像素,我在内部会进行dp处理,转成相应手机对应的尺寸。字体单位sp1也在内部进行相应的到安卓sp的转换。这就是本库适配的原理。
接下来:看下不同手机,不同分辨率下的效果:

三星S7 分辨率:2560x1440 log

Google pixsel XL 分辨率:2560x1440 带虚拟键 log

Google pixsel2 分辨率:1920x1080 带虚拟键 log

华为P9 分辨率:1920x1080 log

联想手机 分辨率:1280x720 log

上述若干不同分辨率的手机,完美实现了适配,最为重要的是:

再也不用拿着设计稿去想这控件的宽高到底取多少dp
再也不用去计算百分比了(如果使用百分比控件完成适配)
再也不用去跟UI MM去解释什么是dp了

而且细心的同学肯定发现,最底下有3条横向的细线很奇怪,效果图怎么会出这种图。其实那3条横线只是为了说明适配效果,我特意加上去的。现在效果图的尺寸是 1920x1080,现在照抄宽度px1080,和宽度的一半px540.大家可以看到多款手机型号和分辨率不同,但是宽度条正好充满了全部和充满了一半,证明适配效果良好。

二、网络请求框架Retrofit2封装

1.Retrofit+RxJava 优雅的处理服务器返回异常、错误

异常&错误

实际开发经常有这种情况,比如登录请求,接口返回的 信息包括请求返回的状态:失败还是成功,错误码,User对象等等。如果网络等原因引起的登录失败可以归结为异常,如果是用户信息输入错误导致的登录失败算是错误。

假如服务器返回的是统一数据格式:

/**
 * 标准数据格式
 * @param <T>
 */
public class Response<T> {
    public int state;
    public String message;
    public T data;
}
网络异常导致的登录失败,在使用Retrofit+RxJava请求时都会直接调用subscribe的onError事件;
密码错误导致的登录失败,在使用Retrofit+RxJava请求时都会调用subscribe的onNext事件;

无论是异常还是错误,都要在subscribe里面处理异常信息,如下代码:

APIWrapper.getInstance().login("username", "password")
                .subscribe(new Observer<Response<User>>() {
                    @Override
                    public void onCompleted() {
                    }
                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Response<User> data) {
                        if(data.state == 1001){
                            //.....
                        }else if(data.state == 1002){

                        }
                    }
                });

现在我希望在发生任何错误的情况下,都会调用onError事件,并且由model来处理错误信息。那么,此时我们就应该有一个ExceptionEngine来处理事件流中的错误信息了。 在工作流中处理异常

在正常情况下,我们获取网络数据的流程通常如下:

请求接口->解析数据->更新UI

整个数据请求过程都是发生在Rx中的工作流之中。当有异常产生的时候,我们要尽量不在ui层里面进行判断,换句话说,我们没有必要去告诉ui层具体的错误信息,只需要让他弹出一个信息(Toast或者Dialog)展示我们给它的信息就行。

统一封装,拦截异常错误

统一封装拦截异常错误主要是为了获取具体的错误信息,分发给上层的UI,给用户以提示,增强用户体验。

/**
     * 所以调研接口,统一调用这个方法
     * @param ob
     * @param subscriber
     */
  public void toSubscribe(Observable ob, final ProgressSubscriber subscriber) {
    //数据预处理
    ObservableTransformer<BaseResponse<Object>, Object> result = handleResult();
    Observable observable = ob.compose(result);
    observable.subscribeWith(subscriber);
  }

    /**
     * 默认情况下,发送者和接收者都运行在主线程,但是这显然是不符合实际需求的,我们在日常使用中,
     * 通常用的最多的就是在子线程进行各种耗时操作,然后发送到主线程进行,难道我们就没有办法继续
     * 用这个优秀的库了?想多了你,一个优秀的库如果连这都想不到,怎么能被称为优秀呢,RxJava中有线
     * 程调度器,通过线程调度器,
     * 
     * Transformer的变化:RxJava1.X为rx.Observable.Transformer接口, 继承自
     * Func1<Observable<T>, Observable<R>>, RxJava2.X为io.reactivex.ObservableTransformer<Upstream, Downstream>,是一个独立的接口。
     * Flowable则是FlowableTransformer,如果你使用Flowable,以下ObservableTransformer
     * 替换FlowableTransformer即可。
     * @param <T>
     * @return
     */
  public static <T> ObservableTransformer<BaseResponse<T>, T> handleResult() {
    return new ObservableTransformer<BaseResponse<T>, T>() {
      @Override public Observable<T> apply(Observable<BaseResponse<T>> tObservable) {
        return tObservable.flatMap(new Function<BaseResponse<T>, ObservableSource<T>>() {
          @Override public Observable<T> apply(BaseResponse<T> result) {
            //成功后交给界面处理
            if (result.getCode() == BaseProjectConfig.SUCCESS_CODE) {
                return createData(result.getData());
            } else {
                //统一处理服务器返回值非正常结果
                Log.d(BaseProjectConfig.TAG, "统一处理服务器返回值非正常结果apply: " + ServerReturnCode.getReasonByCode(result.getCode()));
                return Observable.error(new ApiException(ServerReturnCode.getReasonByCode(0)));
            }
          }
        })
         /*
          - Schedulers.io()      io操作的线程, 通常io操作,如文件读写,读写数据库、网络信息交互等.
          - Schedulers.computation()      计算线程,适合高计算,数据量高的操作.
          - Schedulers.newThread()      创建一个新线程,适合子线程操作.
          - AndroidSchedulers.mainThread()      Android的主线程,主线程       
         */
        .subscribeOn(Schedulers.io()) //线程调度器,将发送者运行在子线程,subscribeOn(),只有在第一次调用的时候生效,之后不管调用多少次,只会以第一次为准.
        .unsubscribeOn
View on GitHub
GitHub Stars1.1k
CategoryDevelopment
Updated5d ago
Forks205

Languages

Java

Security Score

80/100

Audited on Mar 20, 2026

No findings