2017安卓主流框架搭建?看这篇就够了(下)

四.mvp模式(使用MVPPluge插件,自动生成MVP的类文件以及该插件的改装)

MVP模式理解起来很容易,结合安卓,简单概括:无非就是在activty中将网络请求等与数据相关的操作封装到一个P类中,activty中持有P的引用,同时P中又包含activty中调度View的一些方法,这样activity中只写业务逻辑,请求获取数据全靠P去实现,好处是在请求很多,业务逻辑复杂的情况下整个activity的代码依然清晰,同时activity的职责也更单一。

曾经看到过一句话,大致的意思是:

"代码的规范,业务逻辑的清晰,类之间的解耦等等一定是通过增加而不是减少代码来实现的。”

同样,mvp的问题也就暴露出来了,要实现activity中模块的分离,需要增加P类,需要实现各种接口,因此,之前的项目中一直未使用mvp,都是在activity中写到底,最多就是抽取一些方法到util,helper等类中。
这回虽然引入了mvp,但是实际方法中同样也是分情况来看,如果要实现的功能很简单,或者功能很边缘化,甚至小迭代时间紧,任务重的时候还是直接activity中操作数据,只有在一些比较重要,核心的模块里 通过mvp来做更优雅的实现。
题外话到此,下面重点来说说这次项目搭建中mvp的使用过程。

使用过程:

1.android studio引用 MVPPlugin插件
2.MVPPlugin插件的使用
3.MVPPlugin插件的改造

可以看到这里mvp模式都是围绕一个“ MVPPlugin插件”的东西,这个插件是干嘛的? 其实就是一个帮助开发者一键生成mvp模式所需要的一些接口类,P类等。具体的使用方法可以看看这个

http://mp.weixin.qq.com/s/fo34hyvjzNSURSh_V8y4oQ

如果你之前也只是听说并未真正使用过mvp模式开发,那么这个插件将极大的节约你的mvp上手的时间成本,基本属于拿来就用。 不过用归用,插件帮你生成的那些类的源码还是要好好看看,特别是基类,做到消化吸收!可能自己暂时写不出来,但起码要理解原理。

五.网络框架的接入(RXJava2+Retrofit2.0+OKHTTP)

这三个玩意儿无疑是目前灰常火的项目,但凡做android开发,可以说不一定用过,但绝对都听过,了解过。

Rxjava:

是个很神奇的东西。网上的描述一大堆:什么 事件流推动,响应式编程,观察订阅等等 我刚接触的时候百度了半天,也没弄清楚到底是个啥,使用有啥好处,直到看到这篇文章,
我将作者称为“管神”,水管的管。

http://www.jianshu.com/u/c50b715ccaeb([给初学者的RxJava2.0教程)

哈哈 有一个系列,帮助上手Rxjava,但实际上你可能会跟我一样。 系列文章看了一遍,感觉懂了,但是想在项目里面用,发现用不上。
然后结合Retrofit2.0+OKHTTP直接先在项目里面用起来,用熟练了再把文章看一遍,哦,恍然大悟-事件推动。
说得好像有点云里雾里,先别喷我,咋先用上再说。

Retrofit2.0:

是个很方便的东西,说它方便,是因为它像一个接口,本身没有实现,没有功能,但是你把Gson框架放进去,它就能json解析,你把OKHTTP放进去它就能发送网络请求,你把Rxjava放进去它就能进行发送事件流。
那么整个的连接起来是神马?
RXJava2+Retrofit2.0+OKHTTP+GSON=“发送 网络请求 并自动解析json数据的事件流”
可能你会说了,作者你又装X,神马框架不能发送网络请求,然后解析json数据?
但我会告诉你,这个X我装定了!重点是“事件流”三个字。现在你给我0分,等你把上面推荐的rxjava文章看完理解之后或许你会重新打出97分。
为了增加说服力,这里我给出一个复杂的场景:

同时压缩两张图片,都压缩成功后调用上传接口,并将上传接口返回的部分数据作为参数,请求另外一个接口。

这个需求涉及的东西还不少,图片压缩,线程变换,网络请求嵌套。如果不用rxjava,可能最常规的方法应该是这样:
开两个子线程压缩图片,handler发送成功信号到主线程,while循环等待,两个标识都成功然后发送网络请求,请求成功回调再嵌套一个请求。
上面的实现基本上能满足这个需求,但是无论从代码量,代码可读性等等而言都不是那么优雅,但是如果采用rxjava,利用它自带的线程切换,操作符zip,事件流转换flatMap的话,你可以写出一段逻辑清晰,代码量少的链式代码,,,,,
好吧,可能这样描述无法达到那种 “听到后连我自己都害怕”的效果,,但是,请相信,,效果真的很牛X,谁用谁知道。

基本使用:

1.初始化一个OkHttpClient

  OkHttpClient  mOkHttpClient = new OkHttpClient.Builder()
            .readTimeout(DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            .writeTimeout(DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            //设置连接超时时间
            .connectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            //设置缓存
            .cache(getDefaultCache())
            //日志拦截器
            .addInterceptor(loggingInterceptor)
            //头部拦截器
            .addInterceptor(new HeadsInterceptor())
            //设置SSH 兼容https
            .sslSocketFactory(sslSocketFactory.sSLSocketFactory, sslSocketFactory.trustManager)
            //默认全部信任
            .hostnameVerifier(SSHUtil.getHostnameVerifier())
            .build();

2.通过Retrofit.Builder初始化一个RetrofitApi对象,过程中设置请求代理(就是前面mOkHttpClient ),设置数据解析,设置Rxjaxa

 Retrofit.Builder builder = new Retrofit.Builder()
            //设置网络请求实现
            .client(mOkHttpClient)
            //设置json数据解析实现
            .addConverterFactory(GsonConverterFactory.create())
            //RXJAVA适配器
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create());

    //这里主域名的设置单独来弄,万一后台奇葩,一个app里两个主域名的话可以再建一个API_X的接口类,这里类似的单独再配置他的baseurl
   RetrofitApi  httpApi = builder.baseUrl(Constants.APP_HOST)
            .build()
            .create(RetrofitApi.class);

    //配置了RxJava2CallAdapterFactory即集合RXjava的话httpApi调用xxx方法可以直接返回Observable,然后拿来subscribe
    //不结合RXjava的话返回httpApi调用xxx方法返回Call对象,然后拿来enqueue发请求

    //结合RXjava的优点:更灵活,链式调用,线程切换方便,各种操作符效果吊炸天。 说白了就是可以在处理很复杂嵌套循环请求的时候利用RXJAVA,简化开发
    //不过RXJAVA自身的学习成本的确是个问题,我到现在也是云里雾里,不过既然是框架,,,先用再说啦!

3.调用RetrofitApi实例里的业务接口并处理回调

  httpApi.getIndexData().subscribe(new Observer>() {
        @Override
        public void onSubscribe(Disposable d) {
            
        }

        @Override
        public void onNext(TDataBean value) {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    })
全局封装说明:

真正使用过程中肯定不会每次请求都重复上面过程,都会做封装,这里是给出的封装实例,可能并不完美,欢迎批评指出哈!

三个类,分别是:
HttpUtil:初始化retrofit,并根据服务器主域名生成一个全局的 RetrofitApi对象
RetrofitApi: 注解的方式定义出具体的业务接口
ApiManager:网络请求发起类,通过获取HttpUtil中的retrofit实例,调用retrofit中定义的业务接口并传入参数。

在MVP模式的Presenter 里调用方式如下:

public class LoginPresenter extends BasePresenterImpl implements LoginContract.Presenter {
private void textHttp() {
    ApiManager.login("acount","pwdString").subscribe(new HttpObserver>(mView) {
        @Override
        public void onSucceed(TDataBean value) {

        }

        @Override
        public void onDefeat(TDataBean value) {
            super.onDefeat(value);
        }
    });
}

}

HttpObserver继承自Observer,对请求结果做了进一步的封装,具体见源码

部分源码展示:

1.添加引用依赖

 //OKhttp
compile 'com.squareup.okhttp3:okhttp:3.9.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.7.0'
 //retrofit
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
//rxjava
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

2.请求模块初始化

public class HttpUtil {
//超时时间
private static final long DEFAULT_READ_TIMEOUT_MILLIS = 20;//提交数据超时时间
private static final long DEFAULT_WRITE_TIMEOUT_MILLIS = 20;//提交数据超时时间
private static final long DEFAULT_CONNECT_TIMEOUT_MILLIS = 10;//请求超时时间
//缓存大小
private static final long HTTP_RESPONSE_DISK_CACHE_MAX_SIZE = 10 * 1024 * 1024;
//OkHttpClient
private OkHttpClient mOkHttpClient;
//API接口
private RetrofitApi httpApi;

private HttpUtil() {
    initOKHttp();
    initRetrofit();
}

public static HttpUtil getInstance() {
    return ClassHolder.instace;
}

private static class ClassHolder {
    static final HttpUtil instace = new HttpUtil();
}

private void initOKHttp() {
    //日志拦截器,专业处理请求过程中的日志 ,header、body数据
    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
    //根据包的类型控制日志输出与否
    loggingInterceptor.setLevel(BasePackageUtil.isApkDebugable() ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);

    //SSH相关设置,处理https请求的,默认全部信任,不添加的话遇到https请求可能会出异常,WebView,Picasso,Gilde等框架都会有此问题
    SSLParams sslSocketFactory = SSHUtil.getSslSocketFactory();

    mOkHttpClient = new OkHttpClient.Builder()
            .readTimeout(DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            .writeTimeout(DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            //设置连接超时时间
            .connectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            //设置缓存
            .cache(getDefaultCache())
            //日志拦截器
            .addInterceptor(loggingInterceptor)
            //头部拦截器
            .addInterceptor(new HeadsInterceptor())
            //设置SSH 兼容https
            .sslSocketFactory(sslSocketFactory.sSLSocketFactory, sslSocketFactory.trustManager)
            //默认全部信任
            .hostnameVerifier(SSHUtil.getHostnameVerifier())
            .build();


}

private void initRetrofit() {
    Retrofit.Builder builder = new Retrofit.Builder()
            //设置网络请求实现
            .client(mOkHttpClient)
            //设置json数据解析实现
            .addConverterFactory(GsonConverterFactory.create())
            //RXJAVA适配器
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create());

    //这里主域名的设置单独来弄,万一后台奇葩,一个app里两个主域名的话可以再建一个API_X的接口类,这里类似的单独再配置他的baseurl
    httpApi = builder.baseUrl(Constants.APP_HOST)
            .build()
            .create(RetrofitApi.class);

    //配置了RxJava2CallAdapterFactory即集合RXjava的话httpApi调用xxx方法可以直接返回Observable,然后拿来subscribe
    //不结合RXjava的话返回httpApi调用xxx方法返回Call对象,然后拿来enqueue发请求

    //结合RXjava的优点:更灵活,链式调用,线程切换方便,各种操作符效果吊炸天。 说白了就是可以在处理很复杂嵌套循环请求的时候利用RXJAVA,简化开发
    //不过RXJAVA自身的学习成本的确是个问题,我到现在也是云里雾里,不过既然是框架,,,先用再说啦!

}

public OkHttpClient getmOkHttpClient() {
    return mOkHttpClient;
}

public RetrofitApi getHttpApi() {
    return httpApi;
}

public Cache getDefaultCache() {
    String dir = BaseFileUtil.getHttpCacheDir();
    File file = new File(dir);
    Cache cache = new Cache(file, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE);
    return cache;
}

}

3.API封装与调用

public interface RetrofitApi {
/*获取首页数据*/
@POST(Constants.FUNCTION_INDEX)
Observable> getIndexData();

/*登录*/
@POST(Constants.FUNCTION_LOGIN)
Observable> login(@Body JsonObject object);
}

public class ApiManager {
//统一设置线程
private static  Observable subscribeOn(Observable observable) {
    return observable.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread());
}
//获取RetrofitApi实例
private static RetrofitApi getJavaApi() {
    return HttpUtil.getInstance().getHttpApi();
}

/***************************************业务逻辑接口**************************************/
    /*获取首页数据*/
public static Observable> getIndexData() {
    Observable> observable = getJavaApi().getIndexData();
    return subscribeOn(observable);
}

/*获取首页数据*/
public static Observable> login(String username, String pwd) {
    JsonObject data = new JsonObject();
    data.addProperty("mobile", username);
    data.addProperty("password", pwd);
    data.addProperty("device_token", DeviceUtils.getDeviceId());
    Observable> observable = getJavaApi().login(data);
    return subscribeOn(observable);
}
}

完整的demo地址:
https://gitee.com/lunguoguo/revised_development_framework.git (已更新)

你可能感兴趣的:(2017安卓主流框架搭建?看这篇就够了(下))