二,配合RxJava 使用:
  1. 更改定义的接口,返回值不再是一个 Call ,而是返回的一个 Observble:

public interface MovieService {
//获取豆瓣Top250 榜单
@GET(“top250”)
Observable getTop250(@Query(“start”) int start, @Query(“count”)int count);
}

2.创建 Retrofit 的时候添加如下代码:

addCallAdapterFactory(RxJava2CallAdapterFactory.create())

3.添加转换器Converter(将 json 转为 JavaBean):

addConverterFactory(GsonConverterFactory.create())

举实际项目中使用的例子:

retrofit = new Retrofit.Builder()
.client(okHttpBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(BASE_URL)
.build();

4.Activity 或者 Fragment 中传入 DisposableObserver 建立订阅关系:

Subscription subscription = movieService.getTop250(0,20)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver() {
@Override
public void onComplete() {

}
@Override
public void onError(Throwable e) {

}
@Override
public void onNext(MovieSubject movieSubject) {
mMovieAdapter.setMovies(movieSubject.subjects);
mMovieAdapter.notifyDataSetChanged();
}
});

5.加入RxJava的好处:

  • 加入 RxJava 后的网络请求,返回不再是一个 Call ,而是一个 Observable。
  • 在Activity / Fragment 中传入一个Subscriber 建立订阅关系,就可以在 onNext 中处理结果了。
  • RxJava 的好处是帮我处理 线程之间的切换,我们可以在指定 订阅的在哪个线程,观察在哪个线程。
  • 可以 通过操作符 进行数据变换。
  • 整个过程都是链式的,简化逻辑。其中FlatMap 操作符 还可以解除多层嵌套的问题。

RxJava 很强大,能帮我处理很多复杂的场景,如果熟练使用的话,那么能提升我们的开发效率。

三,加入 OkHttp 配置:

通过OkHttpClient 可以配置很多东西,比如 链接超时时间,缓存,拦截器 等等。代码如下:

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接 超时时间
builder.writeTimeout(DEFAULT_TIME_OUT,TimeUnit.SECONDS);//写操作 超时时间
builder.readTimeout(DEFAULT_TIME_OUT,TimeUnit.SECONDS);//读操作 超时时间
builder.retryOnConnectionFailure(true);//错误重连

// 添加公共参数拦截器
BasicParamsInterceptor basicParamsInterceptor = new BasicParamsInterceptor.Builder()
.addHeaderParam(“userName”,“”)//添加公共参数
.addHeaderParam(“device”,“”)
.build();

builder.addInterceptor(basicParamsInterceptor);

// 创建Retrofit
mRetrofit = new Retrofit.Builder()
.client(builder.build())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(ApiConfig.BASE_URL)
.build();

列举项目中用到的如下:

//项目中设置头信息
Interceptor headerInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request.Builder requestBuilder = originalRequest.newBuilder()
.addHeader(“Accept-Encoding”, “gzip”)
.addHeader(“Accept”, “application/json”)
.addHeader(“Content-Type”, “application/json; charset=utf-8”)
.method(originalRequest.method(), originalRequest.body());
requestBuilder.addHeader(“Authorization”, "Bearer " + BaseConstant.TOKEN);//添加请求头信息,服务器进行token有效性验证
Request request = requestBuilder.build();
return chain.proceed(request);
}
};
okHttpBuilder.addInterceptor(headerInterceptor);

//项目中创建Retrofit
retrofit = new Retrofit.Builder()
.client(okHttpBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(BASE_URL)
.build();
httpService = retrofit.create(HttpService.class);

封装篇
一,创建一个 统一生成接口实例的管理类 RetrofitServiceManager

创建了一个 RetrofitServiceManager 类,该类采用 单例模式,在 私有的 构造方法中,生成了 Retrofit 实例,并配置了OkHttpClient 和一些 公共配置。
提供了一个create()方法,生成 接口实例,接收 Class泛型。
代码如下:

public class RetrofitServiceManager {
private static final int DEFAULT_TIME_OUT = 5;//超时时间 5s
private static final int DEFAULT_READ_TIME_OUT = 10;
private Retrofit mRetrofit;

private RetrofitServiceManager(){
// 创建 OKHttpClient
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间
builder.writeTimeout(DEFAULT_READ_TIME_OUT,TimeUnit.SECONDS);//写操作 超时时间
builder.readTimeout(DEFAULT_READ_TIME_OUT,TimeUnit.SECONDS);//读操作超时时间

// 添加公共参数拦截器
HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()
.addHeaderParams(“paltform”,“android”)
.addHeaderParams(“userToken”,“1234343434dfdfd3434”)
.addHeaderParams(“userId”,“123445”)
.build();
builder.addInterceptor(commonInterceptor);

// 创建Retrofit
mRetrofit = new Retrofit.Builder()
.client(builder.build())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(ApiConfig.BASE_URL)
.build();
}

private static class SingletonHolder{
private static final RetrofitServiceManager INSTANCE = new RetrofitServiceManager();
}

/**

  • 获取RetrofitServiceManager
  • @return
    */
    public static RetrofitServiceManager getInstance(){
    return SingletonHolder.INSTANCE;
    }

/**

  • 获取对应的Service
  • @param service Service 的 class
  • @param
  • @return
    */
    public T create(Class service){
    return mRetrofit.create(service);
    }

}

接口实例Service都可以用这个来生成,代码如下:

mMovieService = RetrofitServiceManager.getInstance().create(MovieService.class);

二,创建接口,通过第一步获取实例

有了可以获取接口实例的方法,然后创建一个接口,代码如下:

public interface MovieService{
//获取豆瓣Top250 榜单
@GET(“top250”)
Observable getTop250(@Query(“start”) int start, @Query(“count”) int count);

@FormUrlEncoded
@POST(“/x3/weather”)
Call getWeather(@Field(“cityId”) String cityId, @Field(“key”) String key);
}

三,创建一个业务Loader ,如XXXLoder,获取Observable并处理相关业务

创建 Loader 的原因:每一个Api 都写一个接口很麻烦,因此就把 请求逻辑 封装在 一个业务Loader 里面,一个 Loader 里面可以处理多个Api 接口。代码如下:

public class MovieLoader extends ObjectLoader {
private MovieService mMovieService;
public MovieLoader(){
mMovieService = RetrofitServiceManager.getInstance().create(MovieService.class);
}
/**

  • 获取电影列表
  • @param start
  • @param count
  • @return
    */
    public Observable<List> getMovie(int start, int count){
    return observe(mMovieService.getTop250(start , count)).map(new Func1<MovieSubject, List>() {
    @Override
    public List call(MovieSubject movieSubject) {
    return movieSubject.subjects;
    }
    });
    }

public Observable getWeatherList(String cityId,String key){
return observe(mMovieService.getWeather(cityId , key)).map(new Func1<String , String>() {
@Override
public String call(String s) {
//可以处理对应的逻辑后在返回
return s;
}
});
}

public interface MovieService{
//获取豆瓣Top250 榜单
@GET(“top250”)
Observable getTop250(@Query(“start”) int start, @Query(“count”)int count);

@FormUrlEncoded
@POST(“/x3/weather”)
Call getWeather(@Field(“cityId”) String cityId, @Field(“key”) String key);
}
}
创建一个MovieLoader,构造方法中生成了mHttpService,而 Service 中可以定义和业务相关的多个api,比如:例子中的HttpService中,
可以定义和电影相关的多个api,获取电影列表、获取电影详情、搜索电影等api,就不用定义多个接口了。

MovieLoader 是从 ObjectLoader 中继承下来的,ObjectLoader 提取了一些公共的操作。代码如下:
/**

  • 将一些重复的操作提出来,放到父类以免Loader 里每个接口都有重复代码
    /
    public class ObjectLoader {
    /
    *
  • @param observable
  • @param
  • @return
    */
    protected Observable observe(Observable observable){
    return observable
    .subscribeOn(Schedulers.io())
    .unsubscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread());
    }
    }
四,Activity/Fragment 中的调用

创建Loader实例:

mMovieLoader = new MovieLoader();

通过Loader 调用方法获取结果,代码如下:

/**

  • 获取电影列表
    */
    private void getMovieList(){
    mMovieLoader.getMovie(0,10).subscribe(new Action1<List>() {
    @Override
    public void call(List movies) {
    mMovieAdapter.setMovies(movies);
    mMovieAdapter.notifyDataSetChanged();
    }
    }, new Action1() {
    @Override
    public void call(Throwable throwable) {
    Log.e(“TAG”,“error message:”+throwable.getMessage());
    }
    });
    }
五,统一处理结果和错误

1.统一处理请求结果:
现实项目中,所有接口的返回结果都是同一格式,如:

{
“status”: 200,
“message”: “成功”,
“data”: {}
}

在请求api 接口的时候,只关心想要的数据,也就上面的 data{ },其他的东西不太关心,请求失败 的时候可以根据 status 判断进行 错误处理。
包装返回结果:首先需要根据服务端定义的 JSON 结构创建一个 BaseResponse 类,代码如下:

/**

  • 网络请求结果 基类
    */
    public class BaseResponse {
    public int status;
    public String message;
    public T data;
    public boolean isSuccess(){
    return status == 200;
    }
    }

有了统一的格式数据后,我们需要 剥离出data{ }返回给 上层调用者,创建一个 PayLoad 类,代码如下:

/**

  • 剥离 最终数据
    */
    public class PayLoad implements Func1<BaseResponse{
    @Override
    public T call(BaseResponse tBaseResponse) {//获取数据失败时,包装一个Fault 抛给上层处理错误
    if(!tBaseResponse.isSuccess()){
    throw new Fault(tBaseResponse.status,tBaseResponse.message);
    }
    return tBaseResponse.data;
    }
    }

PayLoad 继承自 Func1,接收一个BaseResponse , 就是接口返回的 JSON 数据结构,返回的是 T,就是data{ },判断是否请求成功,请求成功 返回Data,请求失败 包装成一个 Fault 返回给上层统一处理错误。
在Loader类里面获取结果后,通过map 操作符剥离数据。代码如下:

public Observable<List> getMovie(int start, int count){
return observe(mMovieService.getTop250(start,count))
.map(new PayLoad<BaseResponse<List>());
}

2.统一处理错误:
在PayLoad 类里面,请求失败时,抛出了一个Fault 异常给上层,我在Activity/Fragment 中拿到这个异常,然后判断错误码,进行异常处理。在onError () 中添加。
对应 错误码 处理 相应的错误,代码如下:

public void call(Throwable throwable) {
Log.e(“TAG”,“error message:”+throwable.getMessage());
if(throwable instanceof Fault){
Fault fault = (Fault) throwable;
if(fault.getErrorCode() == 404){
//错误处理
}else if(fault.getErrorCode() == 500){
//错误处理
}else if(fault.getErrorCode() == 501){
//错误处理
}
}
}

六,添加公共参数

实际项目中,每个接口都有一些基本的相同的参数,我们称之为公共参数,比如:userId、userToken、userName、deviceId等等,我们不必每个接口都去写,可以写一个拦截器,在拦截器里面拦截请求,为每个请求都添加相同的公共参数。
拦截器代码如下:

/*

  • 拦截器
  • 向请求头里添加公共参数
    */
    public class HttpCommonInterceptor implements Interceptor {
    private Map<String,String> mHeaderParamsMap = new HashMap<>();
    public HttpCommonInterceptor() {
    }
    @Override
    public Response intercept(Chain chain) throws IOException {
    Log.d(“HttpCommonInterceptor”,“add common params”);
    Request oldRequest = chain.request();
    // 添加新的参数,添加到url 中
    /HttpUrl.Builder authorizedUrlBuilder = oldRequest.url().newBuilder()
    .scheme(oldRequest.url().scheme())
    .host(oldRequest.url().host());
    /

// 新的请求
Request.Builder requestBuilder = oldRequest.newBuilder();
requestBuilder.method(oldRequest.method(), oldRequest.body());

//添加公共参数,添加到header中
if(mHeaderParamsMap.size() > 0){
for(Map.Entry<String,String> params:mHeaderParamsMap.entrySet()){
requestBuilder.header(params.getKey(),params.getValue());
}
}
Request newRequest = requestBuilder.build();
return chain.proceed(newRequest);
}

public static class Builder{
HttpCommonInterceptor mHttpCommonInterceptor;
public Builder(){
mHttpCommonInterceptor = new HttpCommonInterceptor();
}

public Builder addHeaderParams(String key, String value){
mHttpCommonInterceptor.mHeaderParamsMap.put(key,value);
return this;
}

public Builder addHeaderParams(String key, int value){
return addHeaderParams(key, String.valueOf(value));
}

public Builder addHeaderParams(String key, float value){
return addHeaderParams(key, String.valueOf(value));
}

public Builder addHeaderParams(String key, long value){
return addHeaderParams(key, String.valueOf(value));
}

public Builder addHeaderParams(String key, double value){
return addHeaderParams(key, String.valueOf(value));
}

public HttpCommonInterceptor build(){
return mHttpCommonInterceptor;
}

}
}

以上就是添加公共参数的拦截器,在 RetrofitServiceManager 类里面加入OkHttpClient 配置就好了。
代码如下:

// 添加公共参数拦截器
HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()
.addHeaderParams(“paltform”,“android”)
.addHeaderParams(“userToken”,“1234343434dfdfd3434”)
.addHeaderParams(“userId”,“123445”)
.build();
builder.addInterceptor(commonInterceptor);

项目使用篇 ----->插入广告!本项目来源于金融研习社App,金融理财类的在线教育

项目是基于RxJava1
1.引入依赖:

compile ‘com.google.code.gson:gson:2.6.2’//导入Gson 库
//导入RxJava 和 RxAndroid
compile ‘io.reactivex.rxjava2:rxandroid:2.0.2’
compile ‘io.reactivex.rxjava2:rxjava:2.x.y’
compile ‘com.squareup.retrofit2:retrofit:2.3.0’//导入retrofit
compile ‘com.squareup.retrofit2:converter-gson:2.3.0’//转换器,请求结果转换成Model
compile ‘com.squareup.retrofit2:adapter-rxjava2:2.3.0’//配合Rxjava 使用
compile ‘com.squareup.okhttp3:logging-interceptor:3.8.1’//添加HttpLoggingInterceptor进行调试

2.创建一个HttpService接口:

public interface HttpService {
/**

  • 获取用户详细资料
    */
    @POST(“api/XXX/GetUserAllDetails”)
    Observable getUserAllDetails(@Body GetUserAllDetailsRequestBean bean);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

建议

当我们出去找工作,或者准备找工作的时候,我们一定要想,我面试的目标是什么,我自己的技术栈有哪些,近期能掌握的有哪些,我的哪些短板 ,列出来,有计划的去完成,别看前两天掘金一些大佬在驳来驳去 ,他们的观点是他们的,不要因为他们的观点,膨胀了自己,影响自己的学习节奏。基础很大程度决定你自己技术层次的厚度,你再熟练框架也好,也会比你便宜的,性价比高的替代,很现实的问题但也要有危机意识,当我们年级大了,有哪些亮点,与比我们经历更旺盛的年轻小工程师,竞争。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!!!!!!!

  • 准备想说怎么样写简历,想象算了,我觉得,技术就是你最好的简历

  • 我希望每一个努力生活的it工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

  • 有什么问题想交流,欢迎给我私信,欢迎评论

【附】相关架构及资料

Android高级技术大纲

面试资料整理

资料领取

点击这里免费获取

内含往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术

会比你便宜的,性价比高的替代,很现实的问题但也要有危机意识,当我们年级大了,有哪些亮点,与比我们经历更旺盛的年轻小工程师,竞争。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!!!!!!!

  • 准备想说怎么样写简历,想象算了,我觉得,技术就是你最好的简历

  • 我希望每一个努力生活的it工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

  • 有什么问题想交流,欢迎给我私信,欢迎评论

【附】相关架构及资料

[外链图片转存中…(img-1eE6THFc-1711370819637)]

[外链图片转存中…(img-dsB5Dd8h-1711370819638)]

资料领取

点击这里免费获取

内含往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐