一.主流的技术框架简介
Android开发中常用的技术架构有三种,MVC,MVP,MVVM。具体讲解
1. MVC
<1> M:Model:模型层
主要用来获取数据,数据的来源包括接口获取,数据库获取,SharedPreferences获取等等途径。并将其解析成Bean对象回调给Controller层。
<2> V:View:视图层
主要用来绘制各个视图,即Activity/Fragment对应的布局XML文件。
<3> C:Controller:控制层
主要接收Model层的回调,控制View层的显示。Activity/Fragment。
MVC中虽然Activity/Fragment是Controller层,来接收Model层的数据回调,但是由于布局的初始化,显示隐藏以及各种布局的切换等等操作也要在Activity/Fragment中完成。所以Activity/Fragment在MVC的模式下即相当于Controller层又相当于View层。当逻辑复杂时Activity/Fragment中的代码就会异常多而且会特别混乱。所以MVP模式诞生了。
2. MVP
MVP作为MVC的演化,解决了MVC上述的缺点。
<1> M:Model:模型层
主要用来获取数据,数据的来源包括接口获取,数据库获取,SharedPreferences获取等等途径。并将其解析成Bean对象回调给Presenter层。
<2> V:View:视图层
主要接收用户指令(用户点击某个按钮请求数据,或者用户进入某个页面请求数据)。然后调用Presenter层的相关方法进行获取数据的操作。然后接收Presenter层获取各种数据的结果回调,显示不同的View操作(比如有数据显示列表,无数据显示暂无数据)。
<3> P:Presenter:呈现层
主要接收View层的指令然后调用Model层的相关方法,去进行获取接口数据或是获取数据库数据等等的操作。然后接收Model层操作后的各种结果回调给View层,做不同的操作。
MVP模式中,View层和Model层是相互独立没有关联的,两个的关联需要借助Presenter层。
3. MVVM
<1> 非Androidx项目DataBinding 基础讲解_jianning-wu的博客-优快云博客
<2> 非Androidx项目DataBinding RecyclerView使用_jianning-wu的博客-优快云博客
<3> 非Androidx项目DataBinding ListView使用_不使用androidx怎么用 databinding 兼容性问题_jianning-wu的博客-优快云博客
二.代码实现
1.Gradle依赖 RxJava&RxAndroid一起使用必须版本相同 都是1.X版本或者2.X版本
//RxJava
implementation 'io.reactivex:rxjava:1.3.2'
//RxAndroid
implementation 'io.reactivex:rxandroid:1.2.1'
//OkHttp
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
2.Model层(Get请求&Post请求&下载图片)
package com.wjn.networkdemo.okhttp.rx;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import static com.wjn.networkdemo.okhttp.rx.RxSaveKey.GET_KEY;
/**
* Get方法Model层
*/
public class GetModel {
private RxAndroidOkHttp mRxAndroidOkHttp;//RxAndroidOkhttp对象
private Observable mObservable = null;
private String mGetUrl = "http://fanyi.youdao.com/openapi.do?keyfrom=imoocdict123456&key=324273592&type=data&doctype=json&version=1.1&q=blue";
private GetPresenter mGetPresenter;
public GetModel(GetPresenter presenter) {
mRxAndroidOkHttp = RxAndroidOkHttp.getInstance();
mGetPresenter = presenter;
}
/**
* Get请求
*/
public void getServiceData() {
if (null != mRxAndroidOkHttp) {
//1.获取Observable被观察者
mObservable = mRxAndroidOkHttp.get(mGetUrl);
if (null != mObservable) {
//2.创建观察者
Subscriber<String> mSubscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
jsonData("");
}
@Override
public void onNext(String s) {
jsonData(s);
}
};
/**
* 3.观察者&被观察者关联
* subscribeOn:设置被观察者所在的线程 Schedulers.io() IO线程
* observeOn:设置观察者所在的线程 AndroidSchedulers.mainThread() UI主线程
* */
Subscription subscription = mObservable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(mSubscriber);
/**
* 4.保存订阅关系以便在合适时机取消订阅关系 避免内存泄漏
* */
RxAndroidOkHttp.getInstance().saveSubscription(GET_KEY, subscription);
}
}
}
/**
* Json数据解析
*/
private void jsonData(String result) {
Log.d("TAG", "result----:" + result);
MyBean bean = new MyBean();
if (!TextUtils.isEmpty(result)) {
String translation = "";
String basic = "";
try {
JSONObject jsonObject = new JSONObject(result);
translation = jsonObject.optString("translation");
basic = jsonObject.optString("basic");
} catch (JSONException ex) {
ex.printStackTrace();
}
bean.setTranslation(translation);
bean.setBasic(basic);
} else {
bean.setTranslation("");
bean.setBasic("");
}
//最终刷新UI
if (null != mGetPresenter) {
mGetPresenter.updateServiceUI(bean);
}
}
/**
* 取消订阅
*/
public void unSubscribe() {
RxAndroidOkHttp.getInstance().unSubscribe(GET_KEY);
}
}
package com.wjn.networkdemo.okhttp.rx;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Map;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import static com.wjn.networkdemo.okhttp.rx.RxSaveKey.POST_KEY;
/**
* Post方法Model层
*/
public class PostModel {
private RxAndroidOkHttp mRxAndroidOkHttp;//RxAndroidOkhttp对象
private Observable mObservable = null;
private String mPostUrl = "http://fanyi.youdao.com/openapi.do";
private PostPresenter mPostPresenter;
public PostModel(PostPresenter presenter) {
mRxAndroidOkHttp = RxAndroidOkHttp.getInstance();
mPostPresenter = presenter;
}
/**
* Post请求
*/
public void postServiceData(Map<String, String> params) {
if (null != mRxAndroidOkHttp) {
//1.获取Observable被观察者
mObservable = mRxAndroidOkHttp.post(mPostUrl, params);
if (null != mObservable) {
//2.创建观察者
Subscriber<String> mSubscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
jsonData("");
}
@Override
public void onNext(String s) {
jsonData(s);
}
};
/**
* 3.观察者&被观察者关联
* subscribeOn:设置被观察者所在的线程 Schedulers.io() IO线程
* observeOn:设置观察者所在的线程 AndroidSchedulers.mainThread() UI主线程
* */
Subscription subscription = mObservable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(mSubscriber);
/**
* 4.保存订阅关系以便在合适时机取消订阅关系 避免内存泄漏
* */
RxAndroidOkHttp.getInstance().saveSubscription(POST_KEY, subscription);
}
}
}
/**
* Json数据解析
*/
private void jsonData(String result) {
Log.d("TAG", "result----:" + result);
MyBean bean = new MyBean();
if (!TextUtils.isEmpty(result)) {
String translation = "";
String basic = "";
try {
JSONObject jsonObject = new JSONObject(result);
translation = jsonObject.optString("translation");
basic = jsonObject.optString("basic");
} catch (JSONException ex) {
ex.printStackTrace();
}
bean.setTranslation(translation);
bean.setBasic(basic);
} else {
bean.setTranslation("");
bean.setBasic("");
}
//最终刷新UI
if (null != mPostPresenter) {
mPostPresenter.updateServiceUI(bean);
}
}
/**
* 取消订阅
*/
public void unSubscribe() {
RxAndroidOkHttp.getInstance().unSubscribe(POST_KEY);
}
}
package com.wjn.networkdemo.okhttp.rx;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import static com.wjn.networkdemo.okhttp.rx.RxSaveKey.LOAD_PICTURE_KEY;
/**
* 下载图片方法Model层
*/
public class LoadPictureModel {
private RxAndroidOkHttp mRxAndroidOkHttp;//RxAndroidOkhttp对象
private Observable mObservable = null;
private String mLoadPictureUrl = "http://upload.site.cnhubei.com/2016/0117/1453000952567.jpg";
private LoadPicturePresenter mLoadPicturePresenter;
public LoadPictureModel(LoadPicturePresenter presenter) {
mRxAndroidOkHttp = RxAndroidOkHttp.getInstance();
mLoadPicturePresenter = presenter;
}
/**
* 下载图片请求
*/
public void loadPictureServiceData() {
if (null != mRxAndroidOkHttp) {
//1.获取Observable被观察者
mObservable = mRxAndroidOkHttp.loadImageViewByUrl(mLoadPictureUrl);
if (null != mObservable) {
//2.创建观察者
Subscriber<byte[]> mSubscriber = new Subscriber<byte[]>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
jsonData(null);
}
@Override
public void onNext(byte[] bytes) {
jsonData(bytes);
}
};
/**
* 3.观察者&被观察者关联
* subscribeOn:设置被观察者所在的线程 Schedulers.io() IO线程
* observeOn:设置观察者所在的线程 AndroidSchedulers.mainThread() UI主线程
* */
Subscription subscription = mObservable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(mSubscriber);
/**
* 4.保存订阅关系以便在合适时机取消订阅关系 避免内存泄漏
* */
RxAndroidOkHttp.getInstance().saveSubscription(LOAD_PICTURE_KEY, subscription);
}
}
}
/**
* Json数据解析
*/
private void jsonData(byte[] bytes) {
Bitmap bitmap = null;
if (null != bytes) {
bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
//最终刷新UI
if (null != mLoadPicturePresenter) {
mLoadPicturePresenter.updateServiceUI(bitmap);
}
}
/**
* 取消订阅
*/
public void unSubscribe() {
RxAndroidOkHttp.getInstance().unSubscribe(LOAD_PICTURE_KEY);
}
}
3.Presenter层(Get请求&Post请求&下载图片)
package com.wjn.networkdemo.okhttp.rx;
/**
* Get方法Presenter层
*/
public class GetPresenter {
private GetCallBack mGetCallBack;
private GetModel mGetModel;
public GetPresenter(GetCallBack callBack) {
mGetCallBack = callBack;
mGetModel = new GetModel(this);
}
/**
* Get请求
*/
public void getServiceData() {
if (null != mGetModel) {
mGetModel.getServiceData();
}
}
/**
* 刷新UI
*/
public void updateServiceUI(MyBean bean) {
if (null == mGetCallBack || null == bean) {
return;
}
mGetCallBack.getResult(bean);
}
/**
* 取消订阅
*/
public void unSubscribe() {
if (null != mGetModel) {
mGetModel.unSubscribe();
}
}
/**
* 回调
*/
public interface GetCallBack {
void getResult(MyBean bean);
}
}
package com.wjn.networkdemo.okhttp.rx;
import java.util.Map;
/**
* Post方法Presenter层
*/
public class PostPresenter {
private PostCallBack mPostCallBack;
private PostModel mPostModel;
public PostPresenter(PostCallBack callBack) {
mPostCallBack = callBack;
mPostModel = new PostModel(this);
}
/**
* Post请求
*/
public void postServiceData(Map<String, String> params) {
if (null != mPostModel) {
mPostModel.postServiceData(params);
}
}
/**
* 刷新UI
*/
public void updateServiceUI(MyBean bean) {
if (null == mPostCallBack || null == bean) {
return;
}
mPostCallBack.postResult(bean);
}
/**
* 取消订阅
*/
public void unSubscribe() {
if (null != mPostModel) {
mPostModel.unSubscribe();
}
}
/**
* 回调
*/
public interface PostCallBack {
void postResult(MyBean bean);
}
}
package com.wjn.networkdemo.okhttp.rx;
import android.graphics.Bitmap;
/**
* 下载图片方法Presenter层
*/
public class LoadPicturePresenter {
private LoadPictureCallBack mLoadPictureCallBack;
private LoadPictureModel mLoadPictureModel;
public LoadPicturePresenter(LoadPictureCallBack callBack) {
mLoadPictureCallBack = callBack;
mLoadPictureModel = new LoadPictureModel(this);
}
/**
* 下载图片请求
*/
public void loadPictureServiceData() {
if (null != mLoadPictureModel) {
mLoadPictureModel.loadPictureServiceData();
}
}
/**
* 刷新UI
*/
public void updateServiceUI(Bitmap bitmap) {
if (null == mLoadPictureCallBack || null == bitmap) {
return;
}
mLoadPictureCallBack.LoadPictureResult(bitmap);
}
/**
* 取消订阅
*/
public void unSubscribe() {
if (null != mLoadPictureModel) {
mLoadPictureModel.unSubscribe();
}
}
/**
* 回调
*/
public interface LoadPictureCallBack {
void LoadPictureResult(Bitmap bitmap);
}
}
4.View层
package com.wjn.networkdemo.okhttp.rx;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
import com.wjn.networkdemo.R;
import java.util.HashMap;
import java.util.Map;
public class OkHttpRxActivity extends AppCompatActivity implements GetPresenter.GetCallBack, PostPresenter.PostCallBack, LoadPicturePresenter.LoadPictureCallBack {
private ImageView mImageView;
private GetPresenter mGetPresenter;
private PostPresenter mPostPresenter;
private LoadPicturePresenter mLoadPicturePresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_okhttp_rx);
mImageView = findViewById(R.id.activity_okhttp_rx_imageview);
mGetPresenter = new GetPresenter(this);
mPostPresenter = new PostPresenter(this);
mLoadPicturePresenter = new LoadPicturePresenter(this);
//Get请求
findViewById(R.id.activity_okhttp_rx_textview1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getData();
}
});
//Post请求
findViewById(R.id.activity_okhttp_rx_textview2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Map<String, String> params = new HashMap<>();
params.put("keyfrom", "imoocdict123456");
params.put("key", "324273592");
params.put("type", "data");
params.put("doctype", "json");
params.put("version", "1.1");
params.put("q", "red");
postData(params);
}
});
//下载图片
findViewById(R.id.activity_okhttp_rx_textview3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadPicture();
}
});
}
/**
* OkHttp Get请求
*/
private void getData() {
if (null != mGetPresenter) {
mGetPresenter.getServiceData();
}
}
/**
* OkHttp Post请求
*/
private void postData(final Map<String, String> params) {
if (null != mPostPresenter) {
mPostPresenter.postServiceData(params);
}
}
/**
* OkHttp 下载图片
*/
private void loadPicture() {
if (null != mLoadPicturePresenter) {
mLoadPicturePresenter.loadPictureServiceData();
}
}
/**
* Get请求回调
*/
@Override
public void getResult(MyBean bean) {
if (null == bean) {
return;
}
String translation = bean.getTranslation();
String basic = bean.getBasic();
String result = "Translation:" + translation + " Basic:" + basic;
Log.d("OkHttpRxActivity", "Get请求回调 result----:" + result);
Log.d("OkHttpRxActivity", "Get请求回调 线程----:" + Thread.currentThread().getName());
}
/**
* Post请求回调
*/
@Override
public void postResult(MyBean bean) {
if (null == bean) {
return;
}
String translation = bean.getTranslation();
String basic = bean.getBasic();
String result = "Translation:" + translation + " Basic:" + basic;
Log.d("OkHttpRxActivity", "Post请求回调 result----:" + result);
Log.d("OkHttpRxActivity", "Post请求回调 线程----:" + Thread.currentThread().getName());
}
/**
* 下载图片回调
*/
@Override
public void LoadPictureResult(Bitmap bitmap) {
if (null != bitmap && !bitmap.isRecycled()) {
mImageView.setImageBitmap(bitmap);
}
Log.d("OkHttpRxActivity", "下载图片回调 线程----:" + Thread.currentThread().getName());
}
/**
* onDestroy方法 测试 具体每个接口取消订阅在自己接口对应的地方取消即可
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (null != mGetPresenter) {
mGetPresenter.unSubscribe();
}
if (null != mPostPresenter) {
mPostPresenter.unSubscribe();
}
if (null != mLoadPicturePresenter) {
mLoadPicturePresenter.unSubscribe();
}
}
}
5.工具类
package com.wjn.networkdemo.okhttp.rx;
import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.subscriptions.CompositeSubscription;
public class RxAndroidOkHttp {
private OkHttpClient mOkHttpClient;//OkHttpClient 对象
private static RxAndroidOkHttp mRxAndroidOkHttp = null;//单例对象
private HashMap<String, CompositeSubscription> mHashMap;//订阅关系集合
/**
* 构造方法
*/
private RxAndroidOkHttp() {
//创建OkHttp对象 以及连接,读,取超时时间
mOkHttpClient = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)//连接时间
.readTimeout(20, TimeUnit.SECONDS)//读时间
.writeTimeout(20, TimeUnit.SECONDS)//写时间
.retryOnConnectionFailure(true)//连接失败后是否重新连接
.build();
//创建存储订阅关系的集合
mHashMap = new HashMap<>();
}
/**
* 获取此单例类对象的方法
*/
public static RxAndroidOkHttp getInstance() {
if (null == mRxAndroidOkHttp) {//单例对象为空
synchronized (RxAndroidOkHttp.class) {
if (null == mRxAndroidOkHttp) {
mRxAndroidOkHttp = new RxAndroidOkHttp();
}
}
}
return mRxAndroidOkHttp;
}
/**
* Get方法
*/
public Observable<String> get(final String url) {
//创建被观察者
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
final Subscriber mSubscriber = subscriber;
if (!mSubscriber.isUnsubscribed()) { //没有取消订阅的时候
//1.创建Request对象 构建一个具体的网络请求对象 包括具体的请求url&请求头&请求体等等
Request request = new Request.Builder().url(url).get().build();
if (null != mOkHttpClient) {
//2.获取Call对象 将具体的网络请求与执行请求的实体进行绑定,形成一个具体的正式的可执行实体
Call call = mOkHttpClient.newCall(request);
//3.Call对象进行网络请求 enqueue异步 execute同步一般不用
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//通知订阅者的错误信息
mSubscriber.onError(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (null != response && response.isSuccessful()) {//通知订阅者的成功信息
mSubscriber.onNext(response.body().string());
} else {//通知订阅者的错误信息
IOException exception = new IOException("Get请求onResponse方法回调异常");
mSubscriber.onError(exception);
}
//通知完毕
mSubscriber.onCompleted();
}
});
}
}
}
});
return observable;
}
/**
* Post方法
*/
public Observable<String> post(final String url, final Map<String, String> params) {
//创建被观察者
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
final Subscriber mSubscriber = subscriber;
if (!mSubscriber.isUnsubscribed()) {//没有取消订阅的时候
//1.获取FormBody.Builder对象
FormBody.Builder builder = new FormBody.Builder();
//2.遍历params 将其放入到FormBody.Builder 对象
if (params != null && !params.isEmpty()) {
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.add(entry.getKey(), entry.getValue());
}
}
//3.获取RequestBody 对象
RequestBody requestBody = builder.build();
//4.创建Request对象 构建一个具体的网络请求对象 包括具体的请求url&请求头&请求体等等
Request request = new Request.Builder().url(url).post(requestBody).build();
if (mOkHttpClient != null) {
//5.获取Call对象 将具体的网络请求与执行请求的实体进行绑定,形成一个具体的正式的可执行实体
Call call = mOkHttpClient.newCall(request);
//6.Call对象进行网络请求 enqueue异步 execute同步一般不用
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//通知订阅者的错误信息
mSubscriber.onError(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (null != response && response.isSuccessful()) {//通知订阅者的成功信息
mSubscriber.onNext(response.body().string());
} else {
IOException exception = new IOException("Post请求onResponse方法回调异常");
mSubscriber.onError(exception);
}
//通知完毕
mSubscriber.onCompleted();
}
});
}
}
}
});
return observable;
}
/**
* 下载图片 Get方法
*/
public Observable<byte[]> loadImageViewByUrl(final String url) {
//创建被观察者
Observable<byte[]> observable = Observable.create(new Observable.OnSubscribe<byte[]>() {
@Override
public void call(Subscriber<? super byte[]> subscriber) {
final Subscriber mSubscriber = subscriber;
if (!mSubscriber.isUnsubscribed()) { //没有取消订阅的时候
//1.创建Request对象 构建一个具体的网络请求对象 包括具体的请求url&请求头&请求体等等
Request request = new Request.Builder().url(url).get().build();
if (null != mOkHttpClient) {
//2.获取Call对象 将具体的网络请求与执行请求的实体进行绑定,形成一个具体的正式的可执行实体
Call call = mOkHttpClient.newCall(request);
//3.Call对象进行网络请求 enqueue异步 execute同步一般不用
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//通知订阅者的错误信息
mSubscriber.onError(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (null != response && response.isSuccessful()) {//通知订阅者的成功信息
byte[] data = response.body().bytes();
if (data != null) {
mSubscriber.onNext(data);
} else {
IOException exception = new IOException("图片下载onResponse方法数据异常");
mSubscriber.onError(exception);
}
} else {
IOException exception = new IOException("图片下载onResponse方法回调异常");
mSubscriber.onError(exception);
}
//通知完毕
mSubscriber.onCompleted();
}
});
}
}
}
});
return observable;
}
/**
* 保存Subscription
*/
public void saveSubscription(String key, Subscription subscription) {
if (TextUtils.isEmpty(key) || null == subscription) {
return;
}
if (mHashMap == null) {
mHashMap = new HashMap<>();
}
if (mHashMap.get(key) != null) {
mHashMap.get(key).add(subscription);
} else {
CompositeSubscription compositeSubscription = new CompositeSubscription();
compositeSubscription.add(subscription);
mHashMap.put(key, compositeSubscription);
}
}
/**
* 取消订阅
*/
public void unSubscribe(String key) {
if (null == mHashMap || TextUtils.isEmpty(key) || !mHashMap.containsKey(key)) {
return;
}
Log.d("TAG", "取消订阅 key----:" + key);
CompositeSubscription compositeSubscription = mHashMap.get(key);
if (compositeSubscription != null) {
compositeSubscription.unsubscribe();
}
mHashMap.remove(key);
}
}
6.补充
<1> RxJava GitHub地址:GitHub - ReactiveX/RxJava: RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.
<2> RxAndroid GitHub地址:GitHub - ReactiveX/RxAndroid: RxJava bindings for Android
<3> 指定被观察者 生产事件的线程。
observable.subscribeOn(Schedulers.newThread())
<4> 指定观察者 接收 & 响应事件的线程。
observable.observeOn(AndroidSchedulers.mainThread())
<5> RxJava线程切换具体实现
RxJava详解(基于2.X版本的功能操作符)_jianning-wu的博客-优快云博客
三.注意事项
1.MVP内存泄漏详见
2.RxJava详见
https://blog.youkuaiyun.com/weixin_37730482/category_10501619.html
3.RxBus详见