最近公司开发使用了大量新技术和新架构,为了让公司的产品能够很好的兼容6.0(之前的请求层一直使用自己写的HttpClient),通过研究,我们决定使用Retrofit+RxJava的架构重写我们的请求层,Retrofit能够很好的构建出一个REST的客户端,而RxJava是一个异步框架,能够让我们避开繁琐而复杂的主线程和额外线程间的切换,Handler的相互发送,使我们能用直观的角度编写代码,增加代码的可读性,对RxJava不熟悉的朋友可以去看《给 Android 开发者的 RxJava 详解》,里面比较清晰而深入地介绍了RxJava框架。
现在开始构筑请求层,要实现Retrofit的请求,首先我们需要按照要求写一个接口类,里面使用的一些注解等等的用法将会在下面的代码注释中说明:
/** * @author Sentox * Created on 2016/4/14. * 描述:Retrofit定义接口类 */ public interface RequestService { /** * "@GET"表示是用get的方式发起请求 * "login?"是请求接口 * "@Query"表示这是一个参数 * "Observable<PassportLoginResult>"是结合RxJava应该返回的被观察者对象,其返回的结果的数据结构为“PassportLoginResult” * 如果是传统的,可以用“Call<NavigationResult>”进行回调 * 等效于:http://passport.duodian.drcom.com.cn/appserver/login?uid=4918211f837efa6c54dfdc2ecbeb4c58&applicationid=X5LK9zNR4bdfdcDi&cjinfo=12345&apiver=2.0&userName=100076&password=111111 **/ @GET("login?") Observable<PassportLoginResult> GetLogin( @Query("uid") String appid, @Query("applicationid") String applicationid, @Query("cjinfo") String cjinfo, @Query("apiver") String apiver, @Query("userName") String userName, @Query("password") String password ); // Call<NavigationResult> GetNavigation( // @Query("appid") String appid // ); /** * "@POST"表示是用post的方式发起请求 * "@FormUrlEncoded",发送form-encoded数据,每个键-值对都要被含有名字的@Field注解和提供值的对象所标注 * 如果希望在发起请求的时候再决定接口的名字,可以用下面注释的方法写,{"方法名(参数)"}写在@POST中, * 在下面调用@Path("方法名") String 参数,来动态加入url * 等效于:http://passport.duodian.drcom.com.cn:80/appserver/userinfo?加上post出去的键值对“accessToken”=》accessToken **/ @FormUrlEncoded @POST("userinfo?")//@POST("{test}?") Observable<GetUserInfoResult> PostToGetUserInfo( //@Path("test") String test, @Field("accessToken") String accessToken, @Field("userName") String userName, @Field("applicationid") String applicationid, @Field("uid") String uid, @Field("cjinfo") String cjinfo, @Field("apiver") String apiver ); /** * @QueryMap 表示将map类型的params对象,转成键值对的形式作为参数传递给后台 */ @POST("userinfo?") Observable<GetUserInfoResult> MapPostToGetUserInfo( @QueryMap Map<String,String> params ); /** * "@Headers" 是用于添加Http请求的方法头的,header不能被互相覆盖。所有具有相同名字的header将会被包含到请求中。 * "@Header" 用于动态添加方法头,可以为空,为空的时候忽略 * "@Body" 用于添加数据结构,该对象将会被Retroofit实例指定的转换器转换,如果没有添加转换器, * 则只有RequestBody可用。请求时根据转换器进行序列化后发送 * **/ @Headers({ "Accept: application/vnd.github.v3.full+json", "User-Agent: Retrofit-Sample-App" }) @POST("users/new") Call<GetUserInfoResult> createUser( @Body GetUserInfoResult user, @Header("Authorization") String authorization ); }
/** * @author Sentox * Created on 2016/4/14. * 描述:Retrofit接口调用管理类(单例) */ public class RetrofitRequestTool { public static RetrofitRequestTool instance; public static String BASE_URL = "后台访问的公共地址"; private RequestService service; /**转换器 * 默认情况下,Retrofit只能够反序列化Http体为OkHttp的ResponseBody类型,并且只能够接受ResponseBody类型的参数作为@body。 * 添加转换器可以支持其他的类型,为了方便的适应流行的序列化库,Retrofit提供了六个兄弟模块: * Gson: com.squareup.retrofit:converter-gson * Jackson: com.squareup.retrofit:converter-jackson * Moshi: com.squareup.retrofit:converter-moshi * Protobuf: com.squareup.retrofit:converter-protobuf * Wire: com.squareup.retrofit:converter-wire * Simple XML: com.squareup.retrofit:converter-simplexml **/ private RetrofitRequestTool(){ Retrofit.Builder builder = new Retrofit.Builder(); Retrofit retrofit = builder //基础url .baseUrl(BASE_URL) //用于Json数据的转换,需要compile 'com.squareup.retrofit2:converter-gson:2.0.0',非必须 .addConverterFactory(GsonConverterFactory.create()) //用于返回Rxjava调用,需要 compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0',非必须 .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); service = retrofit.create(RequestService.class); } public static RetrofitRequestTool getInstance(){ if (instance == null){ synchronized (RetrofitRequestTool.class){ if(instance == null){ instance = new RetrofitRequestTool(); } } } return instance; } public void getLogin(String userName,String password,Subscriber<PassportLoginResult> subscriber){ service.GetLogin("918211f837efa6c54dfdc2ecbeb4c58","X5LK9zNR4bdfdcDi","","2.0",userName,password) .observeOn(AndroidSchedulers.mainThread())//观察者在主线程运行(更新ui) .subscribeOn(Schedulers.newThread())//被观察者在新线程运行(发送请求) .subscribe(subscriber); } public void postToGetUserInfo(String accessToken,Subscriber<GetUserInfoResult> subscriber){ service.PostToGetUserInfo(accessToken, "100076", "X5LK9zNR4bdfdcDi", "4918211f837efa6c54dfdc2ecbeb4c58", "123456", "2.0") .observeOn(AndroidSchedulers.mainThread())//观察者在主线程运行(更新ui) .subscribeOn(Schedulers.newThread())//被观察者在新线程运行(发送请求) .subscribe(subscriber); } public void MappostToGetUserInfo(Map<String,String> map,Subscriber<GetUserInfoResult> subscriber){ service.MapPostToGetUserInfo(map) .observeOn(AndroidSchedulers.mainThread())//观察者在主线程运行(更新ui) .subscribeOn(Schedulers.newThread())//被观察者在新线程运行(发送请求) .subscribe(subscriber); } }
RetrofitRequestTool.getInstance().MappostToGetUserInfo(map, new Subscriber<GetUserInfoResult>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(GetUserInfoResult getUserInfoResult) { if (getUserInfoResult.getResultMsg().getCode().equals("0")) { tv.setText(getUserInfoResult.getMainAccMsg().getNickName()); } else { Toast.makeText(VolleyTestActivity.this, "getUserInfoResult" + getUserInfoResult.getResultMsg().getMsg(), Toast.LENGTH_LONG).show(); } } });一个请求层框架就这样完成了,欢迎指正。