kotlin使用起来非常顺畅,尤其是结合rxjava、设计模式使用,你会发现写代码原来可以这么开心!什么?你还在使用java?赶紧去学一下kotlin吧!我相信你一定会对他爱不释手,kotlin也很容易学,花一天的时间就可以从java切换为kotlin
本文主要介绍如何使用kotlin封装网络请求的工具,结合设计模式华丽的表演~
废话不多说,先上代码:
package http;
import android.support.annotation.NonNull;
import com.campus.donview.donviewcampus.App;
import com.google.gson.Gson;
import java.io.IOException;
import beans.response.FindClassBean;
import beans.response.JoinClassBean;
import beans.response.LoginBean;
import beans.response.RegisterBean;
import beans.response.SendCodeBean;
import comment.LogUit;
import interfaces.HttpCallback;
import io.reactivex.Observable;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import static comment.Constant.FIND_CLASS;
import static comment.Constant.JOIN_CLASS;
import static comment.Constant.LOGIN;
import static comment.Constant.REGISTER;
import static comment.Constant.SEND_CODE;
public class RetrofitUtil {
private static String TAG="RetrofitUtilPrint";
private static volatile RetrofitUtil retrofitUtil;
//以okhttp设置客户端,retorfit与okhttp的结合
private OkHttpClient okHttpClient=new OkHttpClient()
.newBuilder()
.addInterceptor(new Interceptor() {
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request request=chain.request()
.newBuilder()
.addHeader("Content-Type","application/json;charset=UTF-8")//添加请求头
.addHeader("Grpc-Metadata-sessionkey",(App.getInstance().getSession_key()==null?"":App.getInstance().getSession_key()))
.build();
return chain.proceed(request);
}
})
.build();
//初始化retrofit
private Retrofit retrofit=new Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(HttpAddress.BASE)
.client(okHttpClient)
.build();
//使用单例模式获取retrofitUtli工具
public static RetrofitUtil getInstance(){
if (retrofitUtil==null) retrofitUtil=new RetrofitUtil();
synchronized (RetrofitUtil.class){
if (retrofitUtil==null) retrofitUtil=new RetrofitUtil();
}
return retrofitUtil;
}
//网络请求方法的封装
//Object:传递过来的Bean,HttpCallback:自定义的网络请求回调接口,TYPE:业务请求的类型
public void requestNet(Object object, HttpCallback callback, int TYPE){
LogUit.printI(TAG,"object="+object+",typeLogin="+TYPE);
switch (TYPE){
//如果是发送验证码的请求
case SEND_CODE:
//NetRequest是封装所有请求的retrofit所需的网络请求接口
NetRequest netRequest = retrofit.create(NetRequest.class);
//Observable:结合rxjava使用,将返回结果通过rxjava分析
Observable sendCodeToBeanCall= netRequest.createSend(object);
//将结果回调
callback.onResponse(sendCodeToBeanCall,TYPE);
break;
//以下方法与此类似(封装嘛,所以行为相似)
case REGISTER:
NetRequest netRequest2 = retrofit.create(NetRequest.class);
Observable registerBeanObservable= netRequest2.createRegister(object);
callback.onResponse(registerBeanObservable,TYPE);
break;
case LOGIN:
NetRequest netRequest3 = retrofit.create(NetRequest.class);
Observable loginBeanObservable= netRequest3.createLogin(object);
callback.onResponse(loginBeanObservable,TYPE);
break;
case JOIN_CLASS:
NetRequest netRequest4 = retrofit.create(NetRequest.class);
Observable joinClassBeanObservable= netRequest4.createJoin(object);
callback.onResponse(joinClassBeanObservable,TYPE);
break;
case FIND_CLASS:
NetRequest netRequest5 = retrofit.create(NetRequest.class);
Observable findClassBeanObservable= netRequest5.createFind(object);
callback.onResponse(findClassBeanObservable,TYPE);
break;
}
}
}
代码分析:
如注释所言,首先是设置retrofit的代码以及一个单例模式的获取retrofitUtil的代码,然后是requestNet方法请求网络,方法接收三个参数,第一个参数是retrofit网络请求所需的Bean(是个bean类,与okhttp不同,不用转换成json,所有对象都继承于Object),使用时会自动从object拆包为相应的bean类;第二个参数是封装自定义的回调请求接口,用于将结果回调回去使用;第三个参数就是业务类型咯,
贴上HttpCallback:
package interfaces;
import java.io.IOException;
import io.reactivex.Observable;
public interface HttpCallback {
//使用Observable observable,可以兼容各种请求类型的回调
void onResponse(Observable observable, int typeLogin);
}
package beans.response;
import beans.BaseBean;
public class SendCodeBean{
/**
* code : 10000
* message : send code success
*/
private int code;
private String message;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "code="+getCode()+",message="+getMessage();
}
}
retrofit请求网络所需要的接口:
import beans.response.FindClassBean;
import beans.response.JoinClassBean;
import beans.response.LoginBean;
import beans.response.RegisterBean;
import beans.response.SendCodeBean;
import io.reactivex.Observable;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;
public interface NetRequest {
//POST()里面是访问的网址下的具体位置,SendCodeBean是将回调参数转换的bean类,object为传递过去的数据
@POST("user/send_code")
Observable createSend(@Body Object object);
@POST("user/regist")
Observable createRegister(@Body Object object);
@POST("user/login")
Observable createLogin(@Body Object object);
@POST("class/join_class")
Observable createJoin(@Body Object object);
@POST("class/get_classes")
Observable createFind(@Body Object object);
}
以上就是具体与网络交互的代码(没错,是java写的,被骗了>_< 哈哈哈哈)
嗯哼,先别急,接着来,来看一下怎么用kotlin和rxjava处理网络请求的回调数据
package present
import android.os.Message
import com.campus.donview.donviewcampus.App
import com.google.gson.Gson
import java.io.IOException
import java.net.ConnectException
import java.net.SocketTimeoutException
import beans.response.LoginBean
import beans.response.RegisterBean
import beans.response.SendCodeBean
import beans.to.LoginToBean
import beans.to.RegisterToBean
import beans.to.SendCodeToBean
import comment.BaseHandler
import comment.LogUit
import comment.SendMessage
import http.HTTPProxy
import interfaces.HttpCallback
import interfaces.RequestCallBack
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Consumer
import io.reactivex.observers.DisposableObserver
import io.reactivex.schedulers.Schedulers
import comment.Constant.LOGIN
import comment.Constant.REGISTER
import comment.Constant.SEND_CODE
class RegisterPresent//RequestCallBack:封装的回调接口,提高代码兼容性
(private val requestCallBack: RequestCallBack) : HttpCallback {
private val responseData: String? = null
//发送验证码
fun sendCode(sendCodeToBean: SendCodeToBean) {
//HTTPProxy是网络请求工具的代理,sendCodeToBean是具体传递过去的请求数据,即retrofit的requestNet方法里面的object
HTTPProxy.getInstance()!!.execute(this, sendCodeToBean, SEND_CODE)
}
//注册请求
fun register(registerToBean: RegisterToBean) {
//HTTPProxy是网络请求工具的代理,registerToBean是具体传递过去的请求数据,即retrofit的requestNet方法里面的object
//看吧,使用object作为第一个参数,兼容性强,实现代码封装
HTTPProxy.getInstance()!!.execute(this, registerToBean, REGISTER)
}
//登陆请求
fun login(loginToBean: LoginToBean) {
//HTTPProxy是网络请求工具的代理,loginToBean是具体传递过去的请求数据,即retrofit的requestNet方法里面的object
HTTPProxy.getInstance()!!.execute(this, loginToBean, LOGIN)
}
override fun onResponse(responseData: String, typeLogin: Int) {
}
//回调方法
//使用Observable observable方便转换为具体的数据
override fun onResponse(observable: Observable, typeLogin: Int) {
try {
when (typeLogin) {
SEND_CODE ->
//处理验证码请求的回调,转换为Observable,数据包含在SendCodeBean里
managerSendCode(observable as Observable)
LOGIN ->
//处理登录请求
managerLogin(observable as Observable)
REGISTER ->
//处理注册请求
managerRegister(observable as Observable)
}
} catch (classException: ClassCastException) {
classException.printStackTrace()
LogUit.printE(TAG, "类转换出错=" + classException.message)
} catch (e: Exception) {
e.printStackTrace()
LogUit.printE(TAG, "e=" + e.message)
}
LogUit.printI(TAG, "observable=$observable,typeLogin=$typeLogin")
}
//验证码回调处理
private fun managerSendCode(observable: Observable) {
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())//切换到主线程
.subscribe(object : DisposableObserver() {//处理SendCodeBean
override fun onNext(sendCodeBean: SendCodeBean) {
LogUit.printI(TAG, "sendCodeBean=" + sendCodeBean.toString())
when (sendCodeBean.code) {
//请求成功
10000 ->
//见将结果回调给View
requestCallBack.showMessage(100001)
//请求参数中有空
19997 ->
//电话号码为空
requestCallBack.showMessage(19997)
90004 ->
//电话号码不合法
requestCallBack.showMessage(90004)
}
}
//请求错误(一般是网络错误)
override fun onError(e: Throwable) {
LogUit.printE(TAG, "e=$e")
requestCallBack.showMessage(-1)
}
//处理数据后,结束
override fun onComplete() {
}
})
}
//注册回调
private fun managerRegister(observable: Observable) {
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : DisposableObserver() {
override fun onNext(registerBean: RegisterBean) {
LogUit.printI(TAG, "registerBean=" + registerBean.toString())
when (registerBean.code) {
10000 -> requestCallBack.showMessage(10000)
19997 ->
// 请求参数有空 或参数有误 (性别或身份 不正确)
requestCallBack.showMessage(19997)
90004 ->
//电话号码不合法
requestCallBack.showMessage(90004)
90008 ->
// 用户名不合法
requestCallBack.showMessage(90008)
90001 ->
//用户已注册
requestCallBack.showMessage(90001)
19999 ->
//服务器内部错误
requestCallBack.showMessage(19999)
90007 ->
// 验证码不正确
requestCallBack.showMessage(90007)
90009 ->
// 邮件地址不合法
requestCallBack.showMessage(90009)
}
}
override fun onError(e: Throwable) {
LogUit.printE(TAG, "e=$e")
requestCallBack.showMessage(-1)
}
override fun onComplete() {
}
})
}
//登录回调
private fun managerLogin(observable: Observable) {
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer {
override fun onSubscribe(d: Disposable) {}
override fun onNext(loginBean: LoginBean) {
LogUit.printI(TAG, "loginBean=" + loginBean.toString())
when (loginBean.code) {
10000 -> {
requestCallBack.showMessage(10000)
App.getInstance().session_key = loginBean.session_key
App.getInstance().realName = loginBean.user.realname
}
19997 ->
// 请求参数有空 或参数有误 (性别或身份 不正确)
requestCallBack.showMessage(19997)
19999 ->
//内部错误
requestCallBack.showMessage(19999)
90009 ->
// 邮件地址不合法
requestCallBack.showMessage(90009)
90002 ->
// 密码不正确
requestCallBack.showMessage(90002)
90003 ->
// 用户不存在
requestCallBack.showMessage(90003)
}
}
override fun onError(e: Throwable) {
LogUit.printE(TAG, "e=$e")
requestCallBack.showMessage(-1)
}
override fun onComplete() {}
})
}
override fun onFailure(e: IOException) {}
override fun onError(code: Int) {}
companion object {
private val TAG = "RegisterPrint"
}
}
什么?不懂kotlin?java代码也有:
package present;
import android.os.Message;
import com.campus.donview.donviewcampus.App;
import com.google.gson.Gson;
import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import beans.response.LoginBean;
import beans.response.RegisterBean;
import beans.response.SendCodeBean;
import beans.to.LoginToBean;
import beans.to.RegisterToBean;
import beans.to.SendCodeToBean;
import comment.BaseHandler;
import comment.LogUit;
import comment.SendMessage;
import http.HTTPProxy;
import interfaces.HttpCallback;
import interfaces.RequestCallBack;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
import static comment.Constant.LOGIN;
import static comment.Constant.REGISTER;
import static comment.Constant.SEND_CODE;
public class RegisterPresent implements HttpCallback{
private static final String TAG="RegisterPrint";
private RequestCallBack requestCallBack;
private String responseData;
//RequestCallBack:封装的回调接口,提高代码兼容性
public RegisterPresent(RequestCallBack requestCallBack){
this.requestCallBack=requestCallBack;
}
//发送验证码
public void sendCode(SendCodeToBean sendCodeToBean){
//HTTPProxy是网络请求工具的代理,sendCodeToBean是具体传递过去的请求数据,即retrofit的requestNet方法里面的object
HTTPProxy.getInstance().execute(this,sendCodeToBean,SEND_CODE);
}
//注册请求
public void register(RegisterToBean registerToBean){
//HTTPProxy是网络请求工具的代理,registerToBean是具体传递过去的请求数据,即retrofit的requestNet方法里面的object
//看吧,使用object作为第一个参数,兼容性强,实现代码封装
HTTPProxy.getInstance().execute(this,registerToBean,REGISTER);
}
//登陆请求
public void login(LoginToBean loginToBean){
//HTTPProxy是网络请求工具的代理,loginToBean是具体传递过去的请求数据,即retrofit的requestNet方法里面的object
HTTPProxy.getInstance().execute(this,loginToBean,LOGIN);
}
@Override
public void onResponse(String responseData, int typeLogin) {
}
//回调方法
//使用Observable observable方便转换为具体的数据
@Override
public void onResponse(Observable observable, int typeLogin) {
try {
switch (typeLogin){
case SEND_CODE:
//处理验证码请求的回调,转换为Observable,数据包含在SendCodeBean里
managerSendCode((Observable) observable);
break;
case LOGIN:
//处理登录请求
managerLogin((Observable) observable);
break;
case REGISTER:
//处理注册请求
managerRegister((Observable) observable);
break;
}
}
catch (ClassCastException classException){
classException.printStackTrace();
LogUit.printE(TAG,"类转换出错="+classException.getMessage());
}
catch (Exception e){
e.printStackTrace();
LogUit.printE(TAG,"e="+e.getMessage());
}
LogUit.printI(TAG,"observable="+observable+",typeLogin="+typeLogin);
}
//验证码回调处理
private void managerSendCode(Observable observable){
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())//切换到主线程
.subscribe(new DisposableObserver() {//处理SendCodeBean
@Override
public void onNext(SendCodeBean sendCodeBean) {
LogUit.printI(TAG,"sendCodeBean="+sendCodeBean.toString());
switch (sendCodeBean.getCode()) {
//请求成功
case 10000:
//见将结果回调给View
requestCallBack.showMessage(100001);
break;
//请求参数中有空
case 19997:
//电话号码为空
requestCallBack.showMessage(19997);
break;
case 90004:
//电话号码不合法
requestCallBack.showMessage(90004);
break;
}
}
//请求错误(一般是网络错误)
@Override
public void onError(Throwable e) {
LogUit.printE(TAG,"e="+e);
requestCallBack.showMessage(-1);
}
//处理数据后,结束
@Override
public void onComplete() {
}
});
}
//注册回调
private void managerRegister(Observable observable){
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver() {
@Override
public void onNext(RegisterBean registerBean) {
LogUit.printI(TAG,"registerBean="+registerBean.toString());
switch (registerBean.getCode()){
case 10000:
requestCallBack.showMessage(10000);
break;
case 19997:
// 请求参数有空 或参数有误 (性别或身份 不正确)
requestCallBack.showMessage(19997);
break;
case 90004:
//电话号码不合法
requestCallBack.showMessage(90004);
break;
case 90008:
// 用户名不合法
requestCallBack.showMessage(90008);
break;
case 90001:
//用户已注册
requestCallBack.showMessage(90001);
break;
case 19999:
//服务器内部错误
requestCallBack.showMessage(19999);
break;
case 90007:
// 验证码不正确
requestCallBack.showMessage(90007);
break;
case 90009:
// 邮件地址不合法
requestCallBack.showMessage(90009);
break;
}
}
@Override
public void onError(Throwable e) {
LogUit.printE(TAG,"e="+e);
requestCallBack.showMessage(-1);
}
@Override
public void onComplete() {
}
});
}
//登录回调
private void managerLogin(Observable observable){
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) { }
@Override
public void onNext(LoginBean loginBean) {
LogUit.printI(TAG,"loginBean="+loginBean.toString());
switch (loginBean.getCode()){
case 10000:
requestCallBack.showMessage(10000);
App.getInstance().setSession_key(loginBean.getSession_key());
App.getInstance().setRealName(loginBean.getUser().getRealname());
break;
case 19997:
// 请求参数有空 或参数有误 (性别或身份 不正确)
requestCallBack.showMessage(19997);
break;
case 19999:
//内部错误
requestCallBack.showMessage(19999);
break;
case 90009:
// 邮件地址不合法
requestCallBack.showMessage(90009);
break;
case 90002:
// 密码不正确
requestCallBack.showMessage(90002);
break;
case 90003:
// 用户不存在
requestCallBack.showMessage(90003);
break;
}
}
@Override
public void onError(Throwable e) {
LogUit.printE(TAG,"e="+e);
requestCallBack.showMessage(-1);
}
@Override
public void onComplete() {}
});
}
@Override
public void onFailure(IOException e) { }
@Override
public void onError(int code) { }
}
代码比较多,为了让大家看到封装的效果,我把他们都贴上去了,这里重点分析验证码的请求.
如注释所言,这里通过sendCode方法,将包含数据的bean通过网络代理一层层传递过去(稍后给出代码),一直到到retrofit的request方法,然后通过实现onResponse(observable: Observable, typeLogin: Int)方法将回调过来的数据处理掉,处理的方法这里使用了rxjava处理(不懂的只能自己去脑补了~~),使用rxjava的好处就是只需要一行代码就实现子线程和主线程的切换,可以省去写好多handle和sendMessage的代码(对了,使用handle你还要避免内存泄漏)
关于retrofit+okhttp+rxjava的封装已经介绍完,接下来继续介绍下如何使用设计模式让代码更“漂亮”
先上代码:
代理类:
package http
import interfaces.HTTPProxyFace
import interfaces.HttpCallback
import interfaces.HttpInterfaceMode
class HTTPProxy : HTTPProxyFace {
// private HttpInterfaceMode httpInterfaceMode=new HttpMode();//HttpMode是使用Okhttp编写的网络请求mode
private val httpInterfaceMode = RetrofitMode()//RetrofitMode是使用retrofit编写的网络请求mode
//执行所有类型的网络请求的方法
override fun execute(callback: HttpCallback, `object`: Any, TYPE: Int) {
httpInterfaceMode.execute(callback, `object`, TYPE)
}
companion object {
@Volatile
private var httpProxy: HTTPProxy? = null
//单例模式获取对象
val instance: HTTPProxy?
get() {
if (httpProxy == null) httpProxy = HTTPProxy()
synchronized(HTTPProxy::class.java) {
if (httpProxy == null) httpProxy = HTTPProxy()
}
return httpProxy
}
}
}
package http;
import interfaces.HTTPProxyFace;
import interfaces.HttpCallback;
import interfaces.HttpInterfaceMode;
public class HTTPProxy implements HTTPProxyFace {
// private HttpInterfaceMode httpInterfaceMode=new HttpMode();//HttpMode是使用Okhttp编写的网络请求mode
private HttpInterfaceMode httpInterfaceMode=new RetrofitMode();//RetrofitMode是使用retrofit编写的网络请求mode
private static volatile HTTPProxy httpProxy;
//单例模式获取对象
public static HTTPProxy getInstance(){
if (httpProxy==null) httpProxy=new HTTPProxy();
synchronized (HTTPProxy.class){
if (httpProxy==null) httpProxy=new HTTPProxy();
}
return httpProxy;
}
//执行所有类型的网络请求的方法
@Override
public void execute(HttpCallback callback,Object object, int TYPE) {
httpInterfaceMode.execute(callback,object,TYPE);
}
}
具体的Mode:
package http
import interfaces.HttpCallback
import interfaces.HttpInterfaceMode
class RetrofitMode : HttpInterfaceMode {
override fun execute(callback: HttpCallback, `object`: Any, TYPE: Int) {
RetrofitUtil.getInstance().requestNet(`object`, callback, TYPE)
}
}
package http;
import interfaces.HttpCallback;
import interfaces.HttpInterfaceMode;
public class RetrofitMode implements HttpInterfaceMode {
@Override
public void execute(HttpCallback callback, Object object, int TYPE) {
//看吧,具提调用了RetrofitUtil的requestNet方法,将具体参数传递过去
RetrofitUtil.getInstance().requestNet(object,callback,TYPE);
}
}
本文的代码比较多(不建议直接复制粘贴),是为了让读者对代码有整体的了解(抱怨一下,本人当初封装网络请求时,上网找了一下,都是残缺不全的代码,无法满足需求,最后只能自己封装了 _ )重点在于:
@POST("user/send_code")
Observable createSend(@Body Object object);
使用 Observable,将回调数据转换为我们所熟悉的bean类
(2)使用rxjava解析数据时用DisposableObserver将结果解析出来
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
一、面试合集