什么是AOP?
在讲解GoMVP框架的使用之前,我们先了解一下什么是AOP。
面向切面编程
AOP —— Aspect Oriented Program,即面向切面编程,面向切面编程是一种思想,如同面向对象编程一样,都是思想。
一、GoMVP的使用
1、添加依赖与插件
主工程中gradle添加:
buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.1.3' classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.2' }}复制代码
app工程中gradle:
apply plugin: 'com.android.application'apply plugin: 'android-aspectjx'复制代码
app添加GoMVP依赖:
dependencies { implementation 'com.wookii.gomvp:gomvp:1.3.2'}复制代码
app添加AOP配置:
android{ aspectjx { //AOP时,排除所有package路径中包含`android.support`的class文件及库(jar文件) exclude 'android.support' }}复制代码
Demo
public class AnnotationDemoActivity extends AppCompatActivity { @BindView(R.id.button2) Button button; @BindView(R.id.button3) Button button3; @DataSource(RepositoryInjection.class) private LifecyclePresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple_demo); } /** * test @GoBack * @param bean */ @GoBack public void hahaha(MarketBean bean) { GoLog.E("MarketBean is backing:" + bean.getMessage()); } @GoError public void error(String errorMsg) { GoLog.E("error is backing:" + errorMsg); } @OnClick({R.id.button2, R.id.button3}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.button2: break; case R.id.button3: presenter.execute(new MarketPresenterAdapter()); break; } }}复制代码
也许目前这个Demo片段大家看起来难以消化,从它的一些注解能猜测到这是一个基于注解以及AOP实现的MVP框架,那么接下来我们一步步拆分,还原,介绍GoMVP的使用。
2、初始化Retrofit
GoMVP的网络请求框架是基于Retrofit,RxJava,OkHttp的网络框架,为了框架的灵活性,框架本身并不包含Retrofit的创建,这个需要外部提供,也就是使用者自己的Retrofit。创建好后,留着待用。
public class MainRetrofit implements RetrofitConverter { @Override public String host() { return ApiServer.URL_CONTRACT_NET; } @Override public Retrofit createRetrofit() { return XstoreRetrofitManager.getInstance().getRetrofit(host(), null); }}复制代码
首先实现RetrofitConverter类,实现的第一个方法是指定网络请求的host,第二个方法创建一个Retrofit并且create。这里的XstoreRetrofitManager是使用者自己的。
3、初始化数据仓库
在MVP架构中,数据仓库是必不可少的组件(Repository),我们先来创建它。
public class MarketRepository implements GoDataSource { @Override public GoDataSource loadDataFromRepository(Observable observable, Observer observer) { observable.subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer); return this; } @Override public GoCache getGoCache(Context context) { return new DefaultGoCache(context); } //绑定RetrofitConverter,非常关键 @Override public RetrofitConverter onCreateRetrofitConverter() { return new MainRetrofit(); } @Override publicvoid targetClazz(Class clazz) { return MarketBean.class; }}复制代码
作为使用了GoMVP的Repository,必须实现GoDataSource接口,这个接口返回了四个方法功能如下:
1、loadDataFromRepository方法:
当presenter发起操作时,这是核心方法,治理返回了观察者和被观察者,发挥你的想象力可以在这里做一些业务逻辑的处理
2、getGoCache方法:
使用者需要在这里返回一个缓存对象,默认使用由框架DefaultGoCache,后面会对缓存的扩展进行讲解。
3、onCreateRetrofitConverter方法:
最为关键,这个方法里返回的就是我们第二步创建的MainRetrofit对象,这样数据仓库和具体的Retrofit进行了绑定。
4、targetClazz方法:
会接收到一个class对象,这个class对象通常情况下是个JavaBean,这是由使用者 去指定的,指定的地方在Presenter中,有些时候请求返回的Bean并不是我们想要的,可以通过指定的bean做业务上的强转,还是看具体业务你用不用的上了。
4、创建Presenter扩展
在传统的设计中Presenter的扩展都是通过继承来完成的,在GoMVP中摒弃了这样的方式,是通过PresenterAdapter去进行扩展(如果看到这里比较迷糊,下一先跳过这一部分看一下示例再反过头来看这部分内容)。
public class MarketPresenterAdapter extends PresenterAdapter{ @Override public Observable onCreateObservable(Context context, RetrofitConverter retrofitConverter) { Retrofit retrofit = retrofitConverter.createRetrofit(); ApiServer apiServer = retrofit.create(ApiServer.class); HashMapmap = new HashMap<>(); map.put("请求参数1",0); map.put("请求参数2","123"); Observable > observable = apiServer.getSecretKey(map); return observable; } @Override public Pair onSuccessCodePair() { return new Pair("success","true"); } @Override public String onErrorMessageKey() { return "message"; } @Override public Class targetBeanType() { return MarketBean.class; }}复制代码
依旧是四个方法,我们分别解读一下他们的作用
1、onCreateObservable方法:
该方法需要我们创建一个Observable对象,这个对象会在我们第三步创建的Repostory里返回,方法体提供了一个RetrofitConverter对象,用来创建Observable,而这个RetrofitConverter是我们第二步创建出来,第三部绑定的。
2、targetBeanType方法
这个方法很关键,上面说到Repository的targetClazz方法会返回一个class,就是由这个方法指定的,除此之外它还有个更关键的功能,我下面再说。
其他两个onSuccessCodePair和onErrorMessageKey方法现在用不到,后面再讲。
5、使用示例
前面准备了怎么多,我们开始使用。
/** * Demo */public class AnnoDemoActivity extends AppCompatActivity{ @BindView(R.id.button2) Button button; @BindView(R.id.button3) Button button3; @Presenter() private LifecyclePresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple_demo); //绑定数据仓库 presenter.setRepository(new MarketRepository()); } @GoBack public void hahaha(MarketBean bean) { GoLog.E("MarketBean is backing:" + bean.getValue().getMarketData().getAmountRtv()); } @GoError public void error(String errorMsg) { GoLog.E("error is backing:" + errorMsg); } @OnClick({R.id.button2, R.id.button3}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.button2: presenter.execute(new MarketPresenterAdapter()); break; case R.id.button3: break; } }}复制代码
6、使用@Presenter注解初始化Presenter
1、任意一个类型为LifecyclePresenter 的成员变量加上@Presenter注解,在Activity的onCreate时就会被创建好。
@Presenterprivate LifecyclePresenter presenter;复制代码
PS:之所以叫做LifecyclePresenter,是因为它具有生命周期感知功能,无需使用者关心生命周期的问题,比如释放Presenter,同时它内部集成了BKnife,默认会管理BKnife的初始化与解除绑定等与生命周期相关的操作(使用者在自己的工程添加BKnife的依赖即可)。
2、在onCreate中绑定数据仓库
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple_demo); //绑定数据仓库 presenter.setRepository(new MarketRepository());}复制代码
通过new的方式初始化MarketRepository是不优雅的,不建议这样做,真正的做法是使用RepositoryInjection:下一节见。