*/
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);

/**

  • @param apkUrl 下载地址
    */
    @GET()
    @Streaming
    Call downloadNewApk(@Url String apkUrl);

/**

  • 获取推广大使分享图片
    */
    @GET(“api/XXX/InvitedImage”)
    Observable getInvitedImage(@QueryMap Map<String, Object> map);

}

3.创建http请求类,并在里面初始化并配置Retrofit和OkHttp:

public class HttpMethods {
public String TAG = “HttpMethods”;
public static final String CACHE_NAME = “xxx”;
public static String BASE_URL = URLConstant.BASE_URL;
private static final int DEFAULT_CONNECT_TIMEOUT = 30;
private static final int DEFAULT_WRITE_TIMEOUT = 30;
private static final int DEFAULT_READ_TIMEOUT = 30;
private Retrofit retrofit;
private HttpService httpService;
/**

  • 请求失败重连次数
    */
    private int RETRY_COUNT = 0;
    private OkHttpClient.Builder okHttpBuilder;

//构造方法私有
private HttpMethods() {
//手动创建一个OkHttpClient并设置超时时间
okHttpBuilder = new OkHttpClient.Builder();

/**

  • 设置缓存
    */
    File cacheFile = new File(ApplicationContext.context.getExternalCacheDir(), CACHE_NAME);
    Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
    Interceptor cacheInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    if (!NetUtil.isNetworkConnected()) {
    request = request.newBuilder()
    .cacheControl(CacheControl.FORCE_CACHE)
    .build();
    }
    Response response = chain.proceed(request);
    if (!NetUtil.isNetworkConnected()) {
    int maxAge = 0;
    // 有网络时 设置缓存超时时间0个小时
    response.newBuilder()
    .header(“Cache-Control”, “public, max-age=” + maxAge)
    .removeHeader(CACHE_NAME)// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效
    .build();
    } else {
    // 无网络时,设置超时为4周
    int maxStale = 60 * 60 * 24 * 28;
    response.newBuilder()
    .header(“Cache-Control”, “public, only-if-cached, max-stale=” + maxStale)
    .removeHeader(CACHE_NAME)
    .build();
    }
    return response;
    }
    };
    okHttpBuilder.cache(cache).addInterceptor(cacheInterceptor);

/**

  • 设置头信息
    */
    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);

// if (BuildConfig.DEBUG) {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Logger.d(message);
}

});
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//设置 Debug Log 模式
okHttpBuilder.addInterceptor(loggingInterceptor);
// }
/**

  • 设置超时和重新连接
    */
    okHttpBuilder.connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS);
    okHttpBuilder.readTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.SECONDS);
    okHttpBuilder.writeTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS);
    //错误重连
    okHttpBuilder.retryOnConnectionFailure(true);

retrofit = new Retrofit.Builder()
.client(okHttpBuilder.build())
.addConverterFactory(GsonConverterFactory.create())//json转换成JavaBean
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(BASE_URL)
.build();
httpService = retrofit.create(HttpService.class);
}

//在访问HttpMethods时创建单例
private static class SingletonHolder {
private static final HttpMethods INSTANCE = new HttpMethods();

}

//获取单例
public static HttpMethods getInstance() {
return SingletonHolder.INSTANCE;
}

/**

  • 获取retrofit
    */
    public Retrofit getRetrofit() {
    return retrofit;
    }

public void changeBaseUrl(String baseUrl) {
retrofit = new Retrofit.Builder()
.client(okHttpBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(baseUrl)
.build();
httpService = retrofit.create(HttpService.class);
}

/**

  • 获取httpService
    */
    public HttpService getHttpService() {
    return httpService;
    }

/**

  • 设置订阅 和 所在的线程环境
    */
    public void toSubscribe(Observable o, DisposableObserver s) {

o.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(RETRY_COUNT)//请求失败重连次数
.subscribe(s);

}
}

4.设置回调:
调用者自己对请求数据进行处理 成功时 通过result是否等于1分别回调onSuccees和onFault,默认处理了401错误转登录。

public class OnSuccessAndFaultSub extends DisposableObserver implements ProgressCancelListener {
/**

  • 是否需要显示默认Loading
    */
    private boolean showProgress = true;
    private OnSuccessAndFaultListener mOnSuccessAndFaultListener;

private Context context;
private WaitProgressDialog progressDialog;

/**

  • @param mOnSuccessAndFaultListener 成功回调监听
    */
    public OnSuccessAndFaultSub(OnSuccessAndFaultListener mOnSuccessAndFaultListener) {
    this.mOnSuccessAndFaultListener = mOnSuccessAndFaultListener;
    }

/**

  • @param mOnSuccessAndFaultListener 成功回调监听
  • @param context 上下文
    */
    public OnSuccessAndFaultSub(OnSuccessAndFaultListener mOnSuccessAndFaultListener, Context context) {
    this.mOnSuccessAndFaultListener = mOnSuccessAndFaultListener;
    this.context = context;
    progressDialog = new WaitProgressDialog(context, this);
    }

/**

  • @param mOnSuccessAndFaultListener 成功回调监听
  • @param context 上下文
  • @param showProgress 是否需要显示默认Loading
    */
    public OnSuccessAndFaultSub(OnSuccessAndFaultListener mOnSuccessAndFaultListener, Context context, boolean showProgress) {
    this.mOnSuccessAndFaultListener = mOnSuccessAndFaultListener;
    this.context = context;
    progressDialog = new WaitProgressDialog(context, this);
    this.showProgress = showProgress;
    }

private void showProgressDialog() {
if (showProgress && null != progressDialog) {
progressDialog.show();
}
}

private void dismissProgressDialog() {
if (showProgress && null != progressDialog) {
progressDialog.dismiss();
}
}

/**

  • 订阅开始时调用
  • 显示ProgressDialog
    */
    @Override
    public void onStart() {
    showProgressDialog();
    }

/**

  • 完成,隐藏ProgressDialog
    */
    @Override
    public void onComplete() {
    dismissProgressDialog();
    progressDialog = null;
    }

/**

  • 对错误进行统一处理
  • 隐藏ProgressDialog
    */
    @Override
    public void onError(Throwable e) {
    try {

if (e instanceof SocketTimeoutException) {//请求超时
} else if (e instanceof ConnectException) {//网络连接超时
mOnSuccessAndFaultListener.onFault(“网络连接超时”);
} else if (e instanceof SSLHandshakeException) {//安全证书异常
mOnSuccessAndFaultListener.onFault(“安全证书异常”);
} else if (e instanceof HttpException) {//请求的地址不存在
int code = ((HttpException) e).code();
if (code == 504) {
mOnSuccessAndFaultListener.onFault(“网络异常,请检查您的网络状态”);
} else if (code == 404) {
mOnSuccessAndFaultListener.onFault(“请求的地址不存在”);
} else {
mOnSuccessAndFaultListener.onFault(“请求失败”);
}
} else if (e instanceof UnknownHostException) {//域名解析失败
mOnSuccessAndFaultListener.onFault(“域名解析失败”);
} else {
mOnSuccessAndFaultListener.onFault(“error:” + e.getMessage());
}
} catch (Exception e2) {
e2.printStackTrace();
} finally {
Log.e(“OnSuccessAndFaultSub”, “error:” + e.getMessage());
dismissProgressDialog();
progressDialog = null;

}

}

/**

  • 当result等于1回调给调用者,否则自动显示错误信息,若错误信息为401跳转登录页面。
  • ResponseBody body = response.body();//获取响应体
  • InputStream inputStream = body.byteStream();//获取输入流
  • byte[] bytes = body.bytes();//获取字节数组
  • String str = body.string();//获取字符串数据
    */
    @Override
    public void onNext(ResponseBody body) {
    try {
    final String result = CompressUtils.decompress(body.byteStream());
    Log.e(“body”, result);
    JSONObject jsonObject = new JSONObject(result);
    int resultCode = jsonObject.getInt(“ErrorCode”);
    if (resultCode == 1) {
    mOnSuccessAndFaultListener.onSuccess(result);
    } else {

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

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

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

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

最后

文末放一个小福利给大家,点击我的GitHub即可领取

群内有许多技术大牛,有任何问题,欢迎广大网友一起来交流,群内还不定期免费分享高阶Android学习视频资料和面试资料包~

偷偷说一句:群里高手如云,欢迎大家加群和大佬们一起交流讨论啊!

存中…(img-tR8m8d8S-1711048567246)]
[外链图片转存中…(img-IJPQtN7v-1711048567246)]
[外链图片转存中…(img-gpA80HIa-1711048567247)]
[外链图片转存中…(img-0J4To6dq-1711048567247)]

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

最后

文末放一个小福利给大家,点击我的GitHub即可领取

群内有许多技术大牛,有任何问题,欢迎广大网友一起来交流,群内还不定期免费分享高阶Android学习视频资料和面试资料包~

偷偷说一句:群里高手如云,欢迎大家加群和大佬们一起交流讨论啊!

[外链图片转存中…(img-G65Vc7qz-1711048567248)]

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐