本人小白,最近接触了安卓的网络框架,特来此装逼,有误导之处,请及时指出,谢谢!首先说下retrofit这个东西,之前不知道有这东西,所以网络请求都是直接用socket来写,后来才知道有okhttp3,用了下发现有点复杂,就找到了retrofit2,个人感觉这个网络框架还是挺好用的而且用起来方便简洁,当然他的底层也是基于okhttp,最底层也是使用socket这东西。
retrofit的导入设置
首先是导入以来包,主要是导入retrofit2(这里面自己会导入okhttp3)、rxjava、gson(我这里的服务器使用json交互的,讲道理一般也是用这个的吧~~),大概是下面这些,应该没复制少
compile 'com.squareup.retrofit2:retrofit:2.0.1'compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'compile 'io.reactivex:rxandroid:1.1.0'compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'compile 'com.google.code.gson:gson:2.6.2'
然后先写服务器交互的,api.java,apiService.java
public class Api {
public final static String API_BASE_URL="xxx";//这里是服务器连接的接口的固定部分public static Api instance;//单例private ApiService service;//声明apiservier,下面要通过这个调用与服务器交互的方法//添加请求头拦截器,这个头部也可以在apiservice这个接口中添加Interceptor mInterceptor =new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {try{Request original = chain.request();Request.Builder requestBuilder = original.newBuilder()//添加头部信息.addHeader("key", "value");//这里添加头部,这里可以用addHeader来添加多个头部,如果使用header方法就只能添加一个头部Request request = requestBuilder.build();//用设置好的requestBuilder建立一个新的requestreturn chain.proceed(request);}catch (SocketTimeoutException e){return null;}}};public Api() {HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();//打印出请求的信息的拦截器interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//设置打印请求的记录级别 NONE:不记录; BASIC:请求/响应行; HEADER:请求/响应行+请求头; BODY:请求/响应行+请求头+请求体(所有信息)OkHttpClient okHttpClient = new OkHttpClient.Builder()//建立OkHttpClient,OkHttp3的连接及设置.connectTimeout(10, TimeUnit.SECONDS)//请求连接超时10秒,这里有个writeTimeout没设置,方法跟其他超时的设置一样.connectTimeout(20 * 1000, TimeUnit.MILLISECONDS)//请求连接超时20秒.readTimeout(20 * 1000, TimeUnit.MILLISECONDS)//数据传输超时20秒.addInterceptor(mInterceptor)//添加请求头的拦截器.addInterceptor(interceptor)//打印请求信息拦截器.retryOnConnectionFailure(true)//连接失败后重试(断网重连).build();Retrofit retrofit = new Retrofit.Builder()//建立Retrofit.baseUrl(API_BASE_URL)//连接服务器的基础接口.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//添加Rx适配器.addConverterFactory(GsonConverterFactory.create()) // 添加Gson转换器.client(okHttpClient)//设置OkHttp.build();service = retrofit.create(ApiService.class);//为retrofit创建请求服务器的接口.ApiService为一个接口,内部定义了请求服务器的方法}public static Api getInstance() {
//获取单例if (instance == null)instance = new Api();return instance;}//定义一个调用APIService中方法的方法,提供给需要使用这个请求的地方调用(get请求)public Observable<VerificationCode> getCode(String header, String moblie) {return service.getCode(moblie,"login");}
}
public interface ApiService {
// @Headers("key:value")//可以在此处添加请求头部,由于项目的头部需要转码,所以在api中设置了//get请求@GET("xxx")//申请类型注释,这里的xxx为此方法的服务器接口的变化部分,实际的接口为(固定+变化)Observable<Data> getCode(@Query("mobile") String mobile, @Query("type") String login);//@query为参数注释,键值为mobile的mobile,键值为type的login//post请求@Multipart//方法注释@POST("token/index/login")Observable<Data2> login(@PartMap Map<String, RequestBody> bodyMap);//返回值为observale被观察者,用于给rxjava异步处理,Data2为一个自定义的类,用于存放返回的数据
}
retrofit常用注释说明:
1.申请类型注释: @GET请求、@POST请求,还有@DELETE请求等;;
2.方法注释:(可以没有),
@Multipart:标明请求方法的一个参数为一个部分,且参数需要有@Part注释;;
@Headers标明为申请的头部(多个),Header为一个;;
@FormUrlEncoded:标明请求参数将使用表单网址编码,参数需要使用@Field;;
3.参数注释:
@Body:参数不做处理直接发出,用于post和put请求;;
@Query(“xxx”):标明此参数的键值为xxx,当参数为数组或List时,会对每一个非空的item加上键值xxx,多用于get请求;;
@QueryMap:参数为一个map的query,其键值为map中的键值,多用于get请求;;
@Part:对应Multipart注释,使用该注解定义的参数类型有以下3种方式可选:
1, 如果类型是okhttp3.MultipartBody.Part,内容将被直接使用,即 @Part MultipartBody.Part xxx
2, 如果类型是RequestBody,那么该值将直接与其内容类型一起使用。 在注释中提供part名称(例如,@Part(“xxx”)RequestBody xxx)。
3, 其他对象类型将通过使用转换器转换为适当的格式。 在注释中提供part名称(例如,@Part(value = “image”, encoding = “8-bit”)Image photo)//value为类型,encoding为编码格式
@PartMap:对应Multipart注释,例:@PartMap Map< String, RequestBody> params,其中String为键值,RequestBody为内容正文(这里在使用时,需要转换表单类型,下面做说明)
注:RequestBody的java中表单类型转换代码:
Map<String, RequestBody> bodyMap = new HashMap<>();
bodyMap.put("id", RequestBody.create(
MediaType.parse("xxx"), mobile));//xxx为表单类型
常用的表单类型有(具体的可以查下Http MIME类型):
1.application/x-www-form-urlencoded(默认)
2.image/jpeg(jpeg格式的图片)
3.multipart/form-data(post的表单格式)
4.text/plain(txt的文本格式)
rxjava的配置
这里需要准备3个类,一个是回调时要执行的接口RxApiCallback,一个是回调执行的方法RxSubscriberCallBack(继承于Subscriber),还有管理订阅者的RxManager;
这里的RxApiCallback,RxManager不是必要存在的, 只是为了更好的处理和管理订阅才有的
public interface RxApiCallback<T> {void onSuccess(T model);void onFailure(int code, String msg);}
rxjava会回调一个继承Subscriber的类,并根据返回情况调用类中的3个方法
public class RxSubscriberCallBack<T> extends Subscriber<T> {private RxApiCallback<T> rxApiCallback;public RxSubscriberCallBack(RxApiCallback<T> mapiCallbackRx){this.rxApiCallback = mapiCallbackRx;}@Overridepublic void onCompleted(){
//事件队列中没有后续事件}@Overridepublic void onError(Throwable e) {
//获取服务器信息失败e.printStackTrace();//网络if (!NetWorkUtils.isNetConnected(App.getAppContext())) {
//是否无网络rxApiCallback.onFailure(0, RescourseUtils.getString(R.string.no_net));}//服务器else{rxApiCallback.onFailure(1, "获取数据失败");}}@Overridepublic void onNext(T t) {
//成功时回调rxApiCallback.onSuccess(t);}
}
public class RxManager {private CompositeSubscription mCompositeSubscription = new CompositeSubscription();// 管理订阅者者//添加订阅者public void add(Observable observable, Subscriber subscriber) {mCompositeSubscription.add(observable.subscribeOn(Schedulers.io())//设置调用方法前在io线程中执行.unsubscribeOn(Schedulers.io())//设置取消订阅在io线程中执行.observeOn(AndroidSchedulers.mainThread())//设置调用方法后在主线程中执行.subscribe(subscriber));//设置订阅者}取消所有订阅者public void clear() {mCompositeSubscription.unsubscribe();// 取消订阅}
}
数据存储类
上面用于数据存储的Data、Data2,其实只是一个普通的类,但是retrofit会根据服务器发回来的键值对应到Data中的属性名来赋值.
class Data{private String name;private String phone;private String sex;(省略:get...set...toString)
}
在 此处的Data:
1.如果服务器回传的数据有name,sex键值的,会对应的给name,sex赋值,phone没有的则不会赋值;;
2.如果服务器回传的数据有like键值但Data中不存在,则不对like进行存储(即忽略这个值);;
使用retrofit+rxjava
前面的都设置好了, 到这里就要开始使用了
public RxManager mRxManager;public onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(main);mRxManager=new RxManager();//创建rx管理者//postMap<String, RequestBody> bodyMap = new HashMap<>();bodyMap.put("mobile", RequestBody.create(MediaType.parse("multipart/form-data"), "123"));//将"123"转为表单写入bodyMap中bodyMap.put("yzcode", RequestBody.create(MediaType.parse("multipart/form-data"), "456"));login( bodyMap);//发送请求//getgetCode("123","456");//发送123,456的get请求
}protected void onDestroy() {super.onDestroy();mRxManager.clear();//取消订阅
}//post请求的login
protected void login(Map<String, RequestBody> bodyMap) {mRxManager.add(Api.getInstance().login(bodyMap),new RxSubscriberCallBack<Data2>(new RxApiCallback<Data2>() {
//创建并加入订阅者@Overridepublic void onSuccess(Data2 model) {
//成功回调Log.i("---login---","success:"+model.toString());}@Overridepublic void onFailure(int code, String msg) {
//失败回调Log.i("---login---","failure:"+msg);}}));}//get请求的getCode
protected void getCode(String mobile, String type) {mRxManager.add(Api.getInstance().getCode(mobile,type),new RxSubscriberCallBack<Data>(new RxApiCallback<Data>() {@Overridepublic void onSuccess(Data model) {Log.i("---getCode---","success:"+model.toString());}@Overridepublic void onFailure(int code, String msg) {Log.i("---getCode---","failure:"+msg);}}));}
结尾吐槽
以上是本人项目中接触到的retrofit+rxjava,个人感觉十分的方便,十分的强大,而且此处的rxjava可以代替eventBus,这个我们下次在装逼.