Android 网络框架以及封装
Android 中在【网络】部分常用的框架组合是:
OkHttp + Retrofit
一,准备
添加权限
![image-20230326164537884](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
1
| <uses-permission android:name="android.permission.INTERNET" />
|
添加依赖
![image-20230326164757266](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
![image-20230326164731781](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation("com.squareup.okhttp3:logging-interceptor:4.9.3")
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.google.code.gson:gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
|
上面直接所有网络相关的依赖都加进去了。
配置网络地址
也可以直接放在Config里面。
好处:
可以这样。
![image-20230326173306893](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| android {
defaultConfig { ... flavorDimensions "versionCode" } buildFeatures { buildConfig true } productFlavors { local { buildConfigField('String', "ENDPOINT", '"http://192.168.50.139:8080/"')
buildConfigField 'String', 'RESOURCE_ENDPOINT', '"http://course-music-dev.ixuea.com/%s"'
dimension = minSdkVersion }
dev { buildConfigField('String', "ENDPOINT", '"http://my-cloud-music-api-sp3-dev.ixuea.com/"')
buildConfigField 'String', 'RESOURCE_ENDPOINT', '"http://course-music-dev.ixuea.com/%s"'
dimension = minSdkVersion }
prod { buildConfigField 'String', 'ENDPOINT', '"http://my-cloud-music-api-sp3.ixuea.com/"'
buildConfigField 'String', 'RESOURCE_ENDPOINT', '"http://course-music.ixuea.com/%s"'
dimension = minSdkVersion } } }
|
![image-20230326165901353](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
在添加了依赖之后,点击 sync 同步。然后 run 一下。
我们的资源网址就在BuildConfig
这个Java类里面了。
我们这里直接放在一个系统的 Config 文件中方便管理。
让APP可以发送 HTTP 请求
一般来说,APP现在不允许发送 Http 请求。
但是 OKHttp 就是 Http 请求。
所以为了测试成功还要再加这模一句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.ixuea.courses.mymusic">
...
<application android:usesCleartextTraffic="true" ....> ... </application>
</manifest>
|
![image-20230326172104068](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
二,OkHttp
用OKHttp 请求网络。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| import android.os.Bundle; import android.util.Log;
import com.example.testandroid.activity.BaseLogicActivity; import com.example.testandroid.config.Config;
import java.io.IOException;
import io.reactivex.rxjava3.annotations.NonNull; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response;
private void testGet() { OkHttpClient client = new OkHttpClient();
String url = Config.ENDPOINT + "v1/sheets";
Request request = new Request.Builder() .url(url) .build();
client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.e(TAG, "onFailure: " + e.getLocalizedMessage()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { Log.d(TAG, "onResponse: " + response.body().string()); } });
}
|
测试成功的样子。
![image-20230326172406897](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
三,Retrofit
OKHttp的具体创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
public static OkHttpClient provideOkHttpClient() { OkHttpClient.Builder okhttpClientBuilder = new OkHttpClient.Builder();
Cache cache = new Cache(AppContext.getInstance().getCacheDir(), Config.NETWORK_CACHE_SIZE); okhttpClientBuilder.cache(cache);
okhttpClientBuilder.connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS);
if (Config.DEBUG) {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.level(HttpLoggingInterceptor.Level.BASIC);
okhttpClientBuilder.addInterceptor(loggingInterceptor); }
return okhttpClientBuilder.build(); }
|
补充:
AppContext:
1 2 3 4 5 6 7 8 9 10
| private static AppContext instance; @Override public void onCreate() { super.onCreate(); instance = this; ... } public static AppContext getInstance() { return instance; }
|
Config:
1 2 3 4 5 6 7 8 9
|
public static final boolean DEBUG = BuildConfig.DEBUG;
public static final long NETWORK_CACHE_SIZE = 1024 * 1024 * 100;
|
Retrofit 的具体创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public static Retrofit provideRetrofit(OkHttpClient okHttpClient) { return new Retrofit.Builder() .client(okHttpClient)
.baseUrl(Config.ENDPOINT)
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(JSONUtil.createGson()))
.build(); }
|
上面有些变量或者工具类要自己创建。
JSONUtil.createGson()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder;
public class JSONUtil { public static Gson createGson() { GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES); Gson gson = gsonBuilder.create();
return gson; } }
|
创建 service
描述 API 请求方式,请求地址,请求参数是什么。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.ixuea.courses.mymusic.component.api;
import io.reactivex.rxjava3.core.Observable; import retrofit2.http.GET; import retrofit2.http.Query;
public interface DefaultService {
@GET("v1/sheets") Observable<String> sheets(@Query(value = "category") String category, @Query(value = "size") int size); }
|
Observable: 网络请求数据打包的返回对象
其实不应该是 String 而是具体返回的是什么 Java 类型在本地搞他的实例类。
Retrofit 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| private DefaultService service;
@Override protected void initDatum() { super.initDatum(); Retrofit retrofit = NetworkModule.provideRetrofit(NetworkModule.provideOkHttpClient()); service = retrofit.create(DefaultService.class); testRetrofitGet(); }
private void testRetrofitGet() { service.sheets(null, 2) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<SheetWrapper>() { @Override public void onSubscribe(@NonNull Disposable d) {
}
@Override public void onNext(@NonNull SheetWrapper sheetWrapper) { Sheet sheet = sheetWrapper.getData().getData().get(0); Log.d(TAG, "onNext" + sheet.getTitle()); }
@Override public void onError(@NonNull Throwable e) { Log.d(TAG, "onError" + e.getMessage()); }
@Override public void onComplete() {
} });
}
|
SheetWrapper:是这个网络请求返回的对象类型。(需要自己对照json去在本地定义对象。)
直接丢String是不行的。
具体问题要具体分析。
![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
四,网络框架封装
网络响应格式封装
BaseResponse
因为网络请求的返回json最外面都是status这种什么的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
public class BaseResponse {
private int status;
private String message;
public int getStatus() { return status; }
public void setStatus(int status) { this.status = status; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public boolean isSucceeded() { return status == 0; } }
|
DetailResponse
列表网络请求会有分页那个。详情就是直接真实data。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
public class DetailResponse<T> extends BaseResponse {
private T data;
public T getData() { return data; }
public void setData(T data) { this.data = data; } }
|
ListResponse
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public class ListResponse<T> extends BaseResponse { private Meta<T> data;
public Meta<T> getData() { return data; }
public void setData(Meta<T> data) { this.data = data; } }
|
Meta 就是那个网络请求列表的很多列,然后有分页的一下设置。
可以说 Meta 就是分页模型。
Meta:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| import java.util.List;
public class Meta<T> {
private Integer next;
private List<T> data;
private Integer total;
private Integer pages;
private Integer size;
private Integer page;
public List<T> getData() { return data; }
public void setData(List<T> data) { this.data = data; }
public Integer getTotal() { return total; }
public void setTotal(Integer total) { this.total = total; }
public Integer getPages() { return pages; }
public void setPages(Integer pages) { this.pages = pages; }
public Integer getSize() { return size; }
public void setSize(Integer size) { this.size = size; }
public Integer getPage() { return page; }
public void setPage(Integer page) { this.page = page; }
public Integer getNext() { return next; }
public void setNext(Integer next) { this.next = next; } }
|
上面应用
现在我们还想请求一个歌单==列表==。
因为是列表,所以用 ListResponse。
DefaultService 改成这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import com.example.testandroid.component.sheet.model.Sheet; import com.example.testandroid.model.response.ListResponse;
import io.reactivex.rxjava3.core.Observable; import retrofit2.http.GET; import retrofit2.http.Query;
public interface DefaultService {
@GET("v1/sheets") Observable<ListResponse<Sheet>> sheets(@Query(value = "category") String category, @Query(value = "size") int size); }
|
然后对应调用的地方只用改一下反省的哪里就可以辣。
1 2 3 4
| service.sheets(null, 2) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<ListResponse<Sheet>>() {
|
其实理解了,还是这个好用。
如果要访问 DetailResponse就直接换对应的就可以。这个简单不赘诉。
公共模型封装
Base
所有模型父类
1 2 3 4 5
|
public class Base { }
|
BaseId
继承 Base 的带 Id 的父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import java.util.Objects;
public class BaseId extends Base{
private String id;
public BaseId() { }
public String getId() { return id; }
public void setId(String id) { this.id = id; }
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; BaseId baseId = (BaseId) o; return Objects.equals(id, baseId.id); }
@Override public int hashCode() { return Objects.hash(id); } }
|
Common
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
public class Common extends BaseId {
private String createdAt;
private String updatedAt;
public String getCreatedAt() { return createdAt; }
public void setCreatedAt(String createdAt) { this.createdAt = createdAt; }
public String getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(String updatedAt) { this.updatedAt = updatedAt; } }
|
创建时间和更新时间。
其他模型
按需继承上面的。
然后父类有的,子类全删了。就行了。
封装自动处理错误
![image-20230601205146324](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
每次网络请求都要重写这么多,显得很臃肿。
就是想,没特殊情况就不用重修占领位置了。
ObserverAdapter
继承这个类,后面的只需要想写谁就行,不必须每个都实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.disposables.Disposable;
public class ObserverAdapter<T> implements Observer<T> { @Override public void onSubscribe(@NonNull Disposable d) {
}
@Override public void onNext(@NonNull T t) {
}
@Override public void onError(@NonNull Throwable e) {
}
@Override public void onComplete() {
} }
|
HttpObserver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| import com.example.testandroid.model.response.BaseResponse; import com.example.testandroid.utils.HttpUtil;
import retrofit2.Response;
public abstract class HttpObserver<T> extends ObserverAdapter<T>{
public abstract void onSucceeded(T data);
public boolean onFailed(T data, Throwable e) {
return false; }
@Override public void onNext(T t) { super.onNext(t); onEnd();
if (isSucceeded(t)) { onSucceeded(t); } else { handlerRequest(t, null); } } @Override public void onError(Throwable e) { super.onError(e); onEnd();
handlerRequest(null, e); }
private boolean isSucceeded(T t) { if (t instanceof Response) {
Response response = (Response) t;
int code = response.code();
if (code >= 200 && code <= 299) { return true; }
} else if (t instanceof BaseResponse) { BaseResponse response = (BaseResponse) t;
return response.isSucceeded(); }
return false; }
private void handlerRequest(T data, Throwable error) { if (onFailed(data, error)) {
} else { ExceptionHandlerUtil.handlerRequest(data,error); }
}
public void onEnd() {
} }
|
ExceptionHandlerUtil.handlerRequest
这个需要【封装Toast】和【Loading对话框】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| import android.text.TextUtils;
import com.example.testandroid.AppContext; import com.example.testandroid.R; import com.example.testandroid.model.response.BaseResponse;
import org.apache.commons.lang3.StringUtils;
import java.net.ConnectException; import java.net.SocketTimeoutException; import java.net.UnknownHostException;
import retrofit2.HttpException; import retrofit2.Response;
public class ExceptionHandlerUtil {
public static <T> void handlerRequest(T data, Throwable error) { if (error != null){ handleException(error); }else { if (data instanceof Response){
Response response = (Response) data;
int code = response.code();
if (code >= 200 && code <= 299) {
} else { handleHttpError(code); } }else if (data instanceof BaseResponse) { BaseResponse response = (BaseResponse) data;
if (TextUtils.isEmpty(response.getMessage())) { TipUtil.showError(R.string.error_unknown); } else { TipUtil.showError(response.getMessage()); } } } }
private static void handleException(Throwable error) { if (error.getCause() != null){ error = error.getCause(); }
if (error instanceof UnknownHostException) { TipUtil.showError(R.string.error_network_unknown_host); } else if (error instanceof ConnectException) { TipUtil.showError(R.string.network_error); } else if (error instanceof SocketTimeoutException) { TipUtil.showError(R.string.error_network_timeout); } else if (error instanceof HttpException) { HttpException exception = (HttpException) error;
int code = exception.code();
handleHttpError(code);
} else if (error instanceof IllegalArgumentException) { TipUtil.showError(R.string.error_parameter); } else { String message = error.getLocalizedMessage(); if (StringUtils.isNotBlank(message)) { message = AppContext.getInstance().getString(R.string.error_unknown_format, message); } else { message = AppContext.getInstance().getString(R.string.error_unknown); } TipUtil.showError(message);
}
}
private static void handleHttpError(int code) { if (code == 401) { TipUtil.showError(R.string.error_network_not_auth);
AppContext.getInstance().logout(); } else if (code == 403) { TipUtil.showError(R.string.error_network_not_permission); } else if (code == 404) { TipUtil.showError(R.string.error_network_not_found); } else if (code == 500) { TipUtil.showError(R.string.error_network_server); } else { TipUtil.showError(R.string.error_unknown); } } }
|
TipUtil
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import com.example.superutils.toast.SuperToast;
public class TipUtil {
public static void showError(int toastResource) { SuperToast.error(toastResource); }
public static void showError(String toast) { SuperToast.error(toast); } }
|
封装到这里
我们可以这样使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| service.sheetDetail("","100000") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new HttpObserver<DetailResponse<Sheet>>() { @Override public void onSucceeded(DetailResponse<Sheet> data) { Log.d("烂",data.getData().getTitle()); }
@Override public boolean onFailed(DetailResponse<Sheet> data, Throwable e) { Log.e("烂","错误为:" + e.getLocalizedMessage()); return false; } });
|
直接 new HttpObserver
以前是直接 new Observer
Observer -> ObserverAdapter ->HttpObserver
ObserverAdapter :是让不用每次都重写四个方法
HttpObserver:则是让网络请求中的错误都能自动处理
我们现在用网络请求:就可以
直接new HttpObserver 然后必须重写 onSucceed 方法。
在这个方法里面去处理网络请求成功的数据结果。
然后错误会被我们封装的自动处理。
如果想自己查看和处理错误。
就重写 onFailed 方法。在这里可以打印查看错误问题。
return false 就还是会自动处理。
return true 就会放弃自动处理,就需要我们在 onFailed 里面写好对应的异常错误处理对策。
网络加载提示封装
就是在做一些网络操作的时候,会显示加载。
不让用户做其他操作。
HttpObserver 新添
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public abstract class HttpObserver<T> extends ObserverAdapter<T>{ private boolean isShowLoading; ...... public HttpObserver(BaseLogicActivity activity,boolean isShowLoading) { super(); this.activity = activity; this.isShowLoading = isShowLoading; }
public HttpObserver(BaseLogicFragment fragment) { super(); this.activity = (BaseLogicActivity) fragment.getActivity(); this.isShowLoading = true; }
@Override public void onSubscribe(Disposable d) { super.onSubscribe(d); if (isShowLoading){ activity.showLoading(); } }
public void onEnd() { if (isShowLoading){ activity.hideLoading(); } } ...... }
|
然后,如果我们想在进行网络请求的时候,显示加载框。
就要传入 activity 和 true
1 2 3 4 5 6 7 8 9
| service.sheetDetail("","100000") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new HttpObserver<DetailResponse<Sheet>>(getHostActivity(),true) { @Override public void onSucceeded(DetailResponse<Sheet> data) { Log.d("烂",data.getData().getTitle()); } });
|
就像上面这样
如果传入的 Fragment ,默认是有加载框的。
Repository封装
因为现在请求网路,每次都要自己去制作service,但是这个service应该是单例的。
所以我们可以在封装完善一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| import com.example.testandroid.component.ad.model.Ad; import com.example.testandroid.component.api.DefaultService; import com.example.testandroid.component.api.NetworkModule; import com.example.testandroid.model.response.ListResponse; import com.example.testandroid.utils.Constant;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.schedulers.Schedulers;
public class DefaultRepository {
private static DefaultRepository instance; private final DefaultService service;
public DefaultRepository(){ service = NetworkModule.provideRetrofit(NetworkModule.provideOkHttpClient()).create(DefaultService.class); }
public synchronized static DefaultRepository getInstance() { if (instance == null) instance = new DefaultRepository(); return instance; }
public Observable<ListResponse<Ad>> ads(int position) { return service.ads(position) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); }
public Observable<ListResponse<Ad>> bannerAd() { return ads(Constant.VALUE0); } }
|
然后用的时候直接:
1 2 3 4 5 6 7 8 9 10 11 12
| Observable<ListResponse<Ad>> ads = DefaultRepository.getInstance().bannerAd();
ads .subscribe(new HttpObserver<ListResponse<Ad>>() { @Override public void onSucceeded(ListResponse<Ad> data) { datum.add(new BannerData( data.getData().getData() )); } });
|
这时候有一个问题,就是内存泄露:RxJava会持有这个Activity。
我们用一个框架来解决。
解决网络请求相关内存泄露
1 2 3
|
implementation "com.uber.autodispose2:autodispose-androidx-lifecycle:2.1.1"
|
然后在申请的时候加一句:
1 2 3 4 5 6 7 8 9 10 11 12 13
| Observable<ListResponse<Ad>> ads = DefaultRepository.getInstance().bannerAd();
ads .to(autoDisposable(AndroidLifecycleScopeProvider.from(this))) .subscribe(new HttpObserver<ListResponse<Ad>>() { @Override public void onSucceeded(ListResponse<Ad> data) { datum.add(new BannerData( data.getData().getData() )); } });
|
就可以了
封装到这里,我们的网络请求就只用:
- service里面写地址
- 直接repository写方法
- 外面调repository
五,总结
![未命名文件 (1)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)