本系列文章集合:从 MVP学习代码封装 (1) - 综述
说在开始
看过上一篇文章的萌新们,应该都熟悉了基本的代码套路,上一篇文章中 基于 :base接口 - abs 基类 - 实现类的封装套路,这个不管放到哪里,我们写框架都基本是这个样子,这是用来搭建框架的基本架构的,但是呢,我们写自己的框架毕竟是对某一类 / 一些功能的封装,如何规划好一个框架中功能呢,我们可是要实现易阅读,易修改,易扩展的功能代码的,况且要是需要实现的功能多的话,如何做好那可是个麻烦事啊。
通过本篇呢,我想让给萌新们提供一个思路:使用模板设计模式,把单个功能抽象成一个模板接口,然后做具体逻辑实现,由框架控制层创建/持有某个功能的具体实现,既可以做到合理划分功能到单一类,在框架控制层中也很容易做某个功能的实现类替换,代码解耦了,也方便扩展替换了,而且最重要的是容易阅读了,修改起来方便很多的,不会到头来自己看不懂自己的代码了。
所以说不论是框架封装,但是最简单的胆码封装,处处都体现出设计模式的思想应用在里面,学好设计模式是我们的必须要做到的,我都认为设计模式是 java 基础中的必会技能了。不熟悉的萌新们抓紧时间啦,我也是最近才开始学习的,不足之处大家多留言啊,欢迎打脸。
话接上文
先来看看新的 UML 类图,不得不承认我画 UML 的水平实在是太 low 了,另外我画的就是个示意图,类,接口里面方法没写全,详细去看代码:
- 模板代码抽象的都是可变的部分,留下固定的部分。这里我们需要抽象出的模板代码是针对 V 层生命周期中可以的部分,具体我们需要针对 3中 View 类型:
- activity
- fragment
- view
这3种 view 类型,都有各自不同的生命周期函数,所以我们需要抽象出3个模板接口:
- ILifecycleProxy 根接口,用来指定泛型的
- interface IActivityLifecycleProxy extends ILifecycleProxy
- interface IFragmentLifecycleProxy extends ILifecycleProxy
- interface ICustomeViewLifecycleProxy extends ILifecycleProxy
具体的我们先抽象一个根接口 ILifecycleProxy ,这样方面我们使用泛型,然后用具体的类型去替换。3个具体的接口分别对应3种 view 类型
- 我们在 BasePersenter 这个 P 层的abs 基类中,我们添加声明周期类型的泛型,用 ILifecycleProxy 这个声明周期根接口这个类型。
public abstract class BasePersenter<V extends IBaseView, L extends ILifecycleProxy>
- 我思考过后呢,决定把抽象出来的可变的view 中生命周期的代码由 P 层对象来实现,在 MVP 架构中 P 层对象就是相当于最外层的控制对象的。然后根据 View 类型的不同, P 层需要实现不同的生命周期接口,鉴于生命周期接口差别的巨大和合理的设计,我在这里根据 View 类型一一对应生成多个 P 层 abs 基类来适应 View 类型。
大家注意泛型的使用,不同的 Persenter 类型在继承 BasePersenter 时,指定了不同的对应的 view 类型的生命周期接口,然后 Persenter 实现了这个生命周期接口。我们在具体的 Persenter 对象中的对应生命周期方法中写自己的逻辑即可,这里我的代码也是演示性质的,实际上是由缺漏的,大家根据实际需求去修改吧,生命周期函数太多了。
- BaseActivityPersenter
public class BaseActivityPersenter<V extends BaseActivity> extends BasePersenter<V, IActivityLifecycleProxy> implements IActivityLifecycleProxy
- BaseFragmentPersenter
public class BaseFragmentPersenter<V extends BaseFragment> extends BasePersenter<V, IFragmentLifecycleProxy> implements IFragmentLifecycleProxy
- BaseCustomeViewPersenter
public class BaseCustomeViewPersenter<V extends BaseCustomeView> extends BasePersenter<V,ICustomeViewLifecycleProxy> implements ICustomeViewLifecycleProxy
- 在 V 层 abs 基类中,合适的地方初始化这个生命周期函数接口对象出来,然后在需要的生命周期函数中去执行这个生命周期函数模版对象的相应方法,我以Activity具个例子,更多的去看demo
public abstract class BaseActivity<V extends BaseActivity, P extends BaseActivityPersenter<V>> extends AppCompatActivity implements IBaseView {
private P mBasePersenter;
protected abstract P createPersenter();
private IActivityLifecycleProxy lifecycleProxy;
public P getPersenter() {
return mBasePersenter;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBasePersenter = createPersenter();
mBasePersenter.attachView((V) this);
lifecycleProxy = getPersenter().createlLifecycleProxy();
// lifecycleProxy = (IActivityLifecycleProxy) Proxy.newProxyInstance(lifecycleProxy.getClass().getClassLoader(), lifecycleProxy.getClass().getInterfaces(), new NotNullnvocationHandler(lifecycleProxy));
lifecycleProxy.onCreate(savedInstanceState);
}
@Override
protected void onPause() {
lifecycleProxy.onPause();
super.onPause();
}
@Override
protected void onResume() {
lifecycleProxy.onResume();
super.onResume();
}
@Override
protected void onStop() {
lifecycleProxy.onStop();
super.onStop();
}
@Override
protected void onStart() {
lifecycleProxy.onStart();
super.onStart();
}
@Override
protected void onRestart() {
lifecycleProxy.onStart();
super.onRestart();
}
@Override
protected void onNewIntent(Intent intent) {
lifecycleProxy.onNewIntent(intent);
super.onNewIntent(intent);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
lifecycleProxy.onSaveInstanceState(outState);
super.onSaveInstanceState(outState);
}
@Override
public void onBackPressed() {
if (lifecycleProxy.onBackPressed()) {
return;
}
super.onBackPressed();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
lifecycleProxy.onRequestPermissionsResult(requestCode, permissions, grantResults);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
lifecycleProxy.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
}
@Override
protected void onDestroy() {
lifecycleProxy.onDestroy();
if (mBasePersenter != null) {
mBasePersenter.detachView();
}
super.onDestroy();
}
}
这里我想说一下,我想用动态代理处理一下 IActivityLifecycleProxy 这个属性,应对这个对象意外为 null 时的情况,但是不知道为啥就是报错,报类型转换错误
最后
基本上代码的思路就是这些了,写完之后,我又掠了掠了思路,的确是对自己的代码封装水平提神很有帮助,程序员这一行真的是用大量的思考和练习时间堆积出来的。
具体来说代码很简单,虽然看起来很简单,但是在写的时候可是报了不少错啊,主要是声明周期太多了,需要考虑在合适的点初始化代码啊。
另外在思考时,我考虑 MVP 架构是更应该说是一种代码书写规范,一个 V 的就应该对应一个 P,P 在不同的 V 之间复用,这个是不切实际的,也是不符合设计规范的,不同的 V 之间实际是由大量差异的,对应 V 来说,他的 P 就是专属与自己的,这在 MVP 的设计来说就是这样的。若是不同的 V 的 P 之间有相同的代码逻辑,那也是把系相同的逻辑代码再封装成工具对象,而不是去思考如何复用 P 。所提体现在这里的是在具体的 V层对象时,传入的 V 的泛型就是自己的类型,具体例子
public class NewsActivity extends BaseActivity<NewsActivity, NewsActivityPersenter> implements INewsView
NewsActivity 中,之前 V 的泛型使用的具体的 INewsView 这个业务接口,这个业务接口是继承的 V 层根接口 IBaseView的,现在我们直接传自己就可以,因为对于 P 来说,我只需要针对一个类型 V 的就行,没机会在 V 直接复用,在实际使用中 V,可以会实现大量业务接口,这样做我们在 P 层写具体业务逻辑时会省略 V 对象在不同业务接口之间来回强转类型。
代码部分是demo 中 step2_1 这部分。
最后是项目地址: BW-MVPDemo