

基于RxJava2+Retrofit2精心打造的Android基础框架,包含网络、上传、下载、缓存、事件总线、权限管理、数据库、图片加载、UI模块,基本都是项目中必用功能,每个模块充分解耦,可自由拓展。
XSnow,X:未知一切,取其通用之意;Snow:雪,取其纯净之意。该框架通用纯净,只依赖公共核心库。
compile 'com.vise.xiaoyaoyou:xsnow:2.1.0'


网络算是项目的灵魂,基本每个项目都离不开网络,而一个简单好用,又支持各种配置的网络访问库就显得尤为重要了。该模块也是XSnow的核心功能,使用简单,支持定制常用配置,如各种拦截器、缓存策略、请求头等。
如果不进行二次封装,上层项目基于RxJava+Retrofit请求网络时需要每个接口都写一个服务接口,这样非常不便利。如何将响应结果通用处理就成为该模块的重点,项目中采用泛型转换方式,将响应结果ResponseBody通过map操作符转换成需要的T,具体实现参考项目中http包下的func包,如果需要Http响应码,也可以将响应结果包装成Response这样进行转换成T,考虑到项目中很少需要Http响应码来进行判定,一般使用服务器自定义的响应码就可以了,故该模块采用ResponseBody统一接收这种处理方式。
CallAdapter.Factory、Converter.Factory、okhttp3.Call.Factory、SSLSocketFactory、HostnameVerifier、ConnectionPool、主机URL、请求头、请求参数、代理、拦截器、Cookie、OKHttp缓存、连接超时时间、读写超时时间、失败重试次数、失败重试间隔时间的一系列配置。第一步需要在application中进行全局初始化以及添加全局相关配置,具体使用如下:
ViseHttp.init(this);ViseHttp.CONFIG()
        //配置请求主机地址
        .baseUrl("http://192.168.1.100/")
        //配置全局请求头
        .globalHeaders(new HashMap<String, String>())
        //配置全局请求参数
        .globalParams(new HashMap<String, String>())
        //配置读取超时时间,单位秒
        .readTimeout(30)
        //配置写入超时时间,单位秒
        .writeTimeout(30)
        //配置连接超时时间,单位秒
        .connectTimeout(30)
        //配置请求失败重试次数
        .retryCount(3)
        //配置请求失败重试间隔时间,单位毫秒
        .retryDelayMillis(1000)
        //配置是否使用cookie
        .setCookie(true)
        //配置自定义cookie
        .apiCookie(new ApiCookie(this))
        //配置是否使用OkHttp的默认缓存
        .setHttpCache(true)
        //配置OkHttp缓存路径
        .setHttpCacheDirectory(new File(ViseHttp.getContext().getCacheDir(), ViseConfig.CACHE_HTTP_DIR))
        //配置自定义OkHttp缓存
        .httpCache(new Cache(new File(ViseHttp.getContext().getCacheDir(), ViseConfig.CACHE_HTTP_DIR), ViseConfig.CACHE_MAX_SIZE))
        //配置自定义离线缓存
        .cacheOffline(new Cache(new File(ViseHttp.getContext().getCacheDir(), ViseConfig.CACHE_HTTP_DIR), ViseConfig.CACHE_MAX_SIZE))
        //配置自定义在线缓存
        .cacheOnline(new Cache(new File(ViseHttp.getContext().getCacheDir(), ViseConfig.CACHE_HTTP_DIR), ViseConfig.CACHE_MAX_SIZE))
        //配置开启Gzip请求方式,需要服务器支持
        .postGzipInterceptor()
        //配置应用级拦截器
        .interceptor(new HttpLogInterceptor()
                .setLevel(HttpLogInterceptor.Level.BODY))
        //配置网络拦截器
        .networkInterceptor(new NoCacheInterceptor())
        //配置转换工厂
        .converterFactory(GsonConverterFactory.create())
        //配置适配器工厂
        .callAdapterFactory(RxJava2CallAdapterFactory.create())
        //配置请求工厂
        .callFactory(new Call.Factory() {
            @Override
            public Call newCall(Request request) {
                return null;
            }
        })
        //配置连接池
        .connectionPool(new ConnectionPool())
        //配置主机证书验证
        .hostnameVerifier(new SSLUtil.UnSafeHostnameVerifier("http://192.168.1.100/"))
        //配置SSL证书验证
        .SSLSocketFactory(SSLUtil.getSslSocketFactory(null, null, null))
        //配置主机代理
        .proxy(new Proxy(Proxy.Type.HTTP, new SocketAddress() {}));后面就是具体调用请求的过程,请求的类型有多种情形,下面就以最常用的几种类型举例说明,具体效果可以查看demo,以下为使用示例:
ViseHttp.BASE(new ApiPostRequest("postFormAuthor")         .addForm("author_name", getString(R.string.author_name))         .addForm("author_nickname", getString(R.string.author_nickname))         .addForm("author_account", "xiaoyaoyou1212")         .addForm("author_github", "https://github.com/xiaoyaoyou1212")         .addForm("author_csdn", "http://blog.csdn.net/xiaoyaoyou1212")         .addForm("author_websit", "http://www.huwei.tech/")         .addForm("author_introduction", getString(R.string.author_introduction)))         .request(new ACallback<String>() {             @Override             public void onSuccess(String data) {             }              @Override             public void onFail(int errCode, String errMsg) {             }         });AuthorModel mAuthorModel = new AuthorModel();mAuthorModel.setAuthor_id(1008);mAuthorModel.setAuthor_name(getString(R.string.author_name));mAuthorModel.setAuthor_nickname(getString(R.string.author_nickname));mAuthorModel.setAuthor_account("xiaoyaoyou1212");mAuthorModel.setAuthor_github("https://github.com/xiaoyaoyou1212");mAuthorModel.setAuthor_csdn("http://blog.csdn.net/xiaoyaoyou1212");mAuthorModel.setAuthor_websit("http://www.huwei.tech/");mAuthorModel.setAuthor_introduction(getString(R.string.author_introduction));ViseHttp.BASE(new ApiPostRequest("postJsonAuthor")         .setJson(GSONUtil.gson().toJson(mAuthorModel)))         .request(new ACallback<String>() {             @Override             public void onSuccess(String data) {             }              @Override             public void onFail(int errCode, String errMsg) {             }         });AuthorModel mAuthorModel = new AuthorModel();mAuthorModel.setAuthor_id(1009);mAuthorModel.setAuthor_name(getString(R.string.author_name));mAuthorModel.setAuthor_nickname(getString(R.string.author_nickname));mAuthorModel.setAuthor_account("xiaoyaoyou1212");mAuthorModel.setAuthor_github("https://github.com/xiaoyaoyou1212");mAuthorModel.setAuthor_csdn("http://blog.csdn.net/xiaoyaoyou1212");mAuthorModel.setAuthor_websit("http://www.huwei.tech/");mAuthorModel.setAuthor_introduction(getString(R.string.author_introduction));ViseHttp.BASE(new ApiPostRequest("postUrlAuthor")         .addUrlParam("appId", "10001")         .addUrlParam("appType", "Android")         .setJson(GSONUtil.gson().toJson(mAuthorModel)))         .request(new ACallback<String>() {             @Override             public void onSuccess(String data) {             }              @Override             public void onFail(int errCode, String errMsg) {             }         });该库提供的上传下载功能比较简洁实用,基本能满足单个线程下的常用相关操作,如果需要多线程和断点续传功能就需要上层实现,也可以依赖如RxDownload库。
由于上传下载功能需要用到网络相关,所以也需要像网络那样进行初始化和添加全局配置。下面是上传下载使用示例,具体效果可以查看demo。
ViseHttp.UPLOAD("addImageFile", new UCallback() {     @Override     public void onProgress(long currentLength, long totalLength, float percent) {     }      @Override     public void onFail(int errCode, String errMsg) {     }}).addFile("androidIcon", getUploadFile(mContext, "test.jpg"))         .baseUrl("https://200.200.200.50/")         .request(new ACallback<Object>() {     @Override     public void onSuccess(Object data) {     }      @Override     public void onFail(int errCode, String errMsg) {     }});ViseHttp.DOWNLOAD("weixin/android/weixin6330android920.apk")         .baseUrl("http://dldir1.qq.com/")         .setFileName(saveName)         .request(new ACallback<DownProgress>() {             @Override             public void onSuccess(DownProgress downProgress) {             }              @Override             public void onFail(int errCode, String errMsg) {             }         });包含内存、磁盘二级缓存以及SharedPreferences缓存,可自由拓展。磁盘缓存支持KEY加密存储,可定制缓存时长。SharedPreferences支持内容安全存储,采用Base64加密解密。
MemoryCache.getInstance().put("authorInfo", mAuthorModel);MemoryCache.getInstance().get("authorInfo");diskCache.put("authorInfo", mAuthorModel);diskCache.get("authorInfo");spCache.put("authorInfo", mAuthorModel);spCache.get("authorInfo");采用Rx响应式编程思想建立的RxBus模块,采用注解方式标识事件消耗地,通过遍历查找事件处理方法。支持可插拔,可替换成EventBus库,只需上层采用的同样是注解方式,那么上层是不需要动任何代码的。
BusFactory.getBus().post(new AuthorEvent().setAuthorModel(mAuthorModel));BusFactory.getBus().register(this);BusFactory.getBus().unregister(this);BusFactory.setBus(new EventBus())传进去即可。采用greenDao数据库,其优势就不多说了,网上有解释,其主要优点就是性能高。该模块定制数据库操作接口,有统一的实现类DBManager,上层只需实现getAbstractDao()方法告知底层DaoSession,增删改查操作不需要关心具体细节,调用DBManager中的方法就行。
DbHelper.getInstance().init(this);DbHelper.getInstance().author().insert(mAuthorModel);DbHelper.getInstance().author().delete(mAuthorModel);DbHelper.getInstance().author().update(mAuthorModel);DbHelper.getInstance().author().loadAll()采用Glide库进行图片加载,支持轻量级图片加载,该模块支持可插拔,可根据需求替换成任意图片加载库,如果项目中对于图片处理要求比较高,那么可以替换成Facebook提供的Fresco库。
LoaderFactory.getLoader().init(this);LoaderFactory.setLoader(new FrescoLoader())传进去即可。由于Android6.0以上系统对于权限管理更严格,安全性也有很大的提高,但是随之带来的就是权限管理的代码编写更麻烦,如在权限被用户拒绝时该怎么提示,或者在用户勾选永远拒绝下该怎么处理。针对此种情况,该模块尽量以最小的调用完成权限的管理,只需要一行代码就搞定权限的申请过程,并返回所有需要的回调结果。
//具体使用效果请查看demo
PermissionManager.instance().with(this).request(new OnPermissionCallback() {
    @Override
    public void onRequestAllow(String permissionName) {
        DialogUtil.showTips(mContext, getString(R.string.permission_control),
                getString(R.string.permission_allow) + "\n" + permissionName);
    }
    @Override
    public void onRequestRefuse(String permissionName) {
        DialogUtil.showTips(mContext, getString(R.string.permission_control),
                getString(R.string.permission_refuse) + "\n" + permissionName);
    }
    @Override
    public void onRequestNoAsk(String permissionName) {
        DialogUtil.showTips(mContext, getString(R.string.permission_control),
                getString(R.string.permission_noAsk) + "\n" + permissionName);
    }}, Manifest.permission.CALL_PHONE);包含基础组件、视图状态管理以及万能适配器。适配器可满足所有基于BaseAdapter的适配器组装,使用方便,易拓展;视图状态管理包含空视图、网络异常、其他异常的重试以及视图切换机制。
//创建视图管理
mStatusLayoutManager = StatusLayoutManager.newBuilder(mContext)
        .contentView(R.layout.status_switch_content_layout)//配置内容视图
        .loadingView(R.layout.loading_layout)//配置加载视图
        .emptyView(R.layout.empty_layout)//配置空视图
        .networkErrorView(R.layout.network_error_layout)//配置网络异常视图
        .otherErrorView(R.layout.other_error_layout)//配置其他异常视图
        .retryViewId(R.id.reload_view)//配置重试ViewID
        .onStatusViewListener(new OnStatusViewListener() {//配置状态监听
            @Override
            public void onShowView(View view, int id) {//显示
            }
            @Override
            public void onHideView(View view, int id) {//隐藏
            }
        })
        .onRetryListener(new OnRetryListener() {//配置重试监听
            @Override
            public void onRetry() {
                //模拟重试,显示加载视图
                mStatusLayoutManager.showLoadingView();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                //加载成功,显示内容视图
                                mStatusLayoutManager.showContentView();
                            }
                        });
                    }
                }).start();
            }
        }).build();mLayoutMain.addView(mStatusLayoutManager.getStatusLayout());关联根视图
mStatusLayoutManager.showLoadingView();//显示加载视图