MVP抽取
描述:
当我们的逻辑功能越来越多,每个功能点都要写一套MVP,是一件很繁琐的事情。因此我们要对MVP的进行封装和抽取。
View 视图层 有activity Fragment view 来代表,UI层面的有时候也会有一些共性问题,比如都是展示成功数据,展示失败数据,展示加载中,加载异常等等。所以针对View 抽取一个接口baseView。
Presenter 中间层 是View Model之间交互的桥梁。Presenter是个中间对象,所以他的抽取只是对View Model的抽取。但是Model没有什么共性特点,业务的处理不一样。所以就剩下View的特点,咱们在初始化P的会传入view的引用,这个view 有可能是Activity或者fragment,所以就要考虑生命周期导致的内存泄漏问题,要及时清除对象之间的依赖关系。
Model 业务逻辑 模型层 负责耗时任务处理,单纯的处理数据,比较独立,这里的写法把M给弱化了。你也可以理解为省略了。这样反而省去了M层和Callback的类,简化之间的逻辑。从上述思路也可以看出,MVP是一种思想,不是固定的代码模版。
一、为什么要抽取?
每一个页面都用到同样的内容,每次都写同样的代码,浪费;
规定代码的编写规范;
多人开发维护变得简单。
二、抽取那些内容
通用的操作
三、设计模式
模板设计模式(让子类的工作模式都按照父类的执行)
单例设计模式
四、具体抽取
MVP抽取概述图:
网络抽取
①创建网络管理类,使用双检索单例设计模式获取对象
public class HttpUtil {
private static HttpUtil httpUtil;
public static HttpUtil getHttpUtil() {
if (httpUtil == null) {
synchronized (HttpUtil.class) {
if (httpUtil == null) {
httpUtil = new HttpUtil();
}
}
}
return httpUtil;
}
}
②在网络管理器的构造中获取Retrofit的builder对象
public class HttpUtil {
private final Retrofit.Builder builder;
private HttpUtil() {
builder = new Retrofit.Builder()
.client(getHttpClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create());
}
}
③使用泛型获取ApiService对象
//一个返回T类型的方法,T的类型的泛型
public class HttpUtil {
public <T> T getService(String baseurl, Class<T> mClass) {
return builder.baseUrl(baseurl).build().create(mClass);
}
}
④自定义OKHTTPClient,设置超时、请求头、拦截器等
public class HttpUtil {
private OkHttpClient getHttpClient() {
//设置本地缓存文件
File file = new File(Constants.PATH_CACHE);
//设置缓存
Cache cache = new Cache(file, 1024 * 1024 * 50);
//设置日志拦截器
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
} else {
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
}
return new OkHttpClient.Builder()
.cache(cache)
.addInterceptor(httpLoggingInterceptor)
.addNetworkInterceptor(new MyCacheIntercepter())
.addInterceptor(new MyCacheIntercepter())
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build();
}
//网络拦截器
public class MyCacheIntercepter implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!isNetworkAvailable(GeekApplication.getApplication())) {
request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
}
Response originalResponse = chain.proceed(request);
if (isNetworkAvailable(GeekApplication.getApplication())) {
int maxAge = 0;
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public ,max-age=" + maxAge)
.build();
} else {
int maxStale = 15 * 60;
return originalResponse.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
}
}
public static boolean isNetworkAvailable(Context context) {
if (context != null) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null) {
return info.isAvailable();
}
}
return false;
}
}
⑤抽取线程切换
public class RxUtil {
/**
* <T ,T > T转换前的对象类型, T 转换后的对象类型
*
* @param <T>
* @return
*/
public static <T> ObservableTransformer<T, T> rxObservableTransformer() {
return new ObservableTransformer<T, T>() {
@Override
public ObservableSource<T> apply(Observable<T> upstream) {
return upstream.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io());
}
};
}
}
⑥观察者抽取
public abstract class BaseObserver<T> implements Observer<T> {
@Override
public void onSubscribe(Disposable d) {
Log.e("TAG", "订阅成功");
}
@Override
public void onError(Throwable e) {
onFail("onError:" + e.getMessage());
}
@Override
public void onComplete() {
Log.e("TAG", "请求完成");
}
@Override
public void onNext(T value) {
onSuccess(value);
}
public abstract void onFail(String error);
protected abstract void onSuccess(T t);
}
⑦使用
HttpManager.getHttpManager().getApiService(ApiService.baseLoginUrl, ApiService.class)
.login(name, pwd)
.compose(RxUtil.<LoginBean>rxTransform())
.subscribe(new BaseObserver<LoginBean>() {
@Override
public void onSucess(LoginBean loginBean) {
if (loginBean.getErrorCode() == 0) {
callBack.onSucess(loginBean);
} else {
callBack.onFail(loginBean.getErrorMsg());
}
}
@Override
public void onFail(String error) {
callBack.onFail(error);
}
});
BaseActivity抽取
public abstract class BaseActivity<P extends BasePresenter, V extends BaseView> extends AppCompatActivity {
protected P mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
ButterKnife.bind(this);
mPresenter = initPresenter();
if (mPresenter != null) {
mPresenter.setmView(initMvpView());
}
initView();//有些子类需要,有些不需要
initData();//有些子类需要,有些不需要,仅仅用普通方法即可
initListener();
}
protected abstract void initListener();
protected abstract void initData();
protected abstract void initView();
protected abstract V initMvpView();
protected abstract P initPresenter();
protected abstract int getLayoutId();
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.onDestory();
mPresenter = null;
}
}
BaseModel抽取
public class BaseModel {
public CompositeDisposable mCompositeDisposable;
public void onDestory() {
//切断所有的Disposable对象
if (mCompositeDisposable != null){
mCompositeDisposable.clear();
}
}
public void addDisposable(Disposable d){
if (mCompositeDisposable == null){
mCompositeDisposable = new CompositeDisposable();
}
mCompositeDisposable.add(d);
}
}
BaseView 抽取
public interface BaseView<T> {
void onSucess(T t);
void onFail(String error);
}
BasePresenter抽取
public abstract class BasePresenter<V extends BaseView> {
protected V mView;
private ArrayList<BaseModel> mModels = new ArrayList<>();
public BasePresenter() {
initMdel();
}
protected abstract void initMdel();
public void setmView(V mView) {
this.mView = mView;
}
public void onDestory() {
//打断P层和V层的联系,
mView = null;
//掐断网络请求
if (mModels.size() > 0) {
for (BaseModel model : mModels) {
model.onDestory();
}
mModels.clear();
}
}
public void addModel(BaseModel model) {
mModels.add(model);
}
}
callback抽取
public interface BaseCallBack<T> {
void onSuccess(T t);
void onFail(String error);
}
MVP抽取案例使用(登录)
M层
public class LoginModel extends BaseModel {
public void login(String name, String password, BaseCallBack<String, String> callBack) {
if (true) {
callBack.onSuccess("登录成功");
} else {
callBack.onFail("登录失败");
}
}
}
P层
public class LoginPresenter extends BasePresenter<LoginView, LoginModel> implements BaseCallBack<String, String> {
public void login(String name, String pwd) {
if (model != null) {
model .login(name, pwd, this);
}
}
@Override
public void onSuccess(String s) {
if (view != null) {
view .onSuccess(s);
}
}
@Override
public void onFail(String s) {
if (view != null) {
view .onFail(s);
}
}
}
V层
public class MainActivity extends BaseActivity<LoginPresenter, LoginView, LoginModel> implements LoginView {
@BindView(R.id.btn_login)
Button btnLogin;
@Override
protected int getLayoutId() {
return R.layout.activity_main;
}
@Override
protected LoginView initMvpView() {
return this;
}
@Override
protected LoginModel initMvpModel() {
return new LoginModel();
}
@Override
protected LoginPresenter initPresnter() {
return new LoginPresenter();
}
@Override
public void onSuccess(String s) {
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
}
@Override
public void onFail(String s) {
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
}
@OnClick({R.id.btn_login})
public void onViewClicked(View view) {
baseP.login("", "");
}
MVP与普通的分离(不需要mvp的页面)
不需要MVP
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
ButterKnife.bind(this);
initMvp();
initView();//有些子类需要,有些不需要
initData();//有些子类需要,有些不需要,仅仅用普通方法即可
initListener();
}
private void initMvp() {}
protected abstract int getLayoutId();
private void initListener() {}
private void initData() {}
protected void initView() {}
}
需要mvp
public abstract class BaseMVPActivity<P extends BasePresenter, V extends BaseView, M extends BaseModel> extends BaseActivity {
protected P presenter;
@Override
public void initMvp() {
super.initMvp();
presenter = initPresnter();
if (presenter != null) {
presenter.addView(initMvpView());
presenter.addModel(initMvpModel());
}
}
protected abstract V initMvpView();
protected abstract M initMvpModel();
protected abstract P initPresnter();
}
Fragment抽取
没有MVP抽取基类
public abstract class BaseFragment extends Fragment {
private Unbinder unbinder;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(getLayoutId(), container, false);
unbinder = ButterKnife.bind(this, view);
initMvp();
initView();
initData();
initListener();
return view;
}
protected void initMvp() {
}
protected void initListener() {
}
protected void initData() {
}
protected void initView() {
}
protected abstract int getLayoutId();
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}
有MVP抽取
public abstract class BaseMvpFragment<P extends BasePresenter, V extends BaseView, M extends BaseModel> extends BaseFragment {
protected P presenter;
@Override
protected void initMvp() {
super.initMvp();
presenter = initPresnter();
if (presenter != null) {
presenter.addView(initMvpView());
presenter.addModel(initMvpModel());
}
}
protected abstract V initMvpView();
protected abstract M initMvpModel();
protected abstract P initPresnter();
}
应用崩溃问题解决:
背景:在发动网络请求的时候,退出当前activity
冲突:此时如果回到主线程更新UI,APP会崩溃
解决:当activity退出时,调用DisPosable.dispose()切断观察者和被观察者的连接,使得观察者无法收到事件&响应事件;当出现多个disposable时,采用Rxjava内置容器CompositeDisposable进行统一管理
CompositeDisposable compositeDisposable = new CompositeDisposable();
//添加disposable到CompositeDisposable容器
compositeDisposable .add();
//清空CompositeDisposable容器,在父类的baseModel中调用
compositeDisposable .clear();
在BaseModel中:
public abstract class BaseModel {
//用于统一切断观察者与被观察者关系
CompositeDisposable compositeDisposable = new CompositeDisposable();
//切断,P层调用
public void destroy() {
compositeDisposable.clear();
}
}
在basePresenter中
public class BasePresenter<V extends BaseView, M extends BaseModel> {
//创建一个集合,用于存放model
protected ArrayList<BaseModel> list = new ArrayList<BaseModel>();
protected V view;
protected M model;
public void addView(V v) {
this.view = v;
}
public void addModel(M m) {
this.model = m;
//添加model
list.add(m);
}
public void destroy() {
//如果view不为空,页面关闭,强制置空,否则内存泄漏
if (view != null) {
view = null;
}
//如果页面关闭,切断网络请求的观察者与被观察者的关系
if (list.size() > 0) {
for (BaseModel baseModel : list) {
baseModel.destroy();
}
}
//如果model不为空,置空
if (model != null) {
model = null;
}
}
}
在BaseMVPActivity中:
/**
* 页面关闭时
* 切断连接
* 内存回收
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (presenter != null) {
presenter.destroy();
}
}