带你动手实现 MVP+Clean架构!

获取微信精选文章,可以定义为一个业务。

在 presentation 层,点击了 Button 按钮,向 Presenter 层,发出获取文章指令 getArticleList()

Presenter 层收到指令,调用 UseCase.execute(),这时就与 domain 层产生联系了。

在 execute 方法中,通过 Repository 接口从 data 层获取数据。

获取数据后,再通过回调,最终 presentation 层拿到数据,进行文章列表展示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码实现

创建 ArticleView

public interface ArticleView extends IView {

void getArticleSuccess(List articleBeanList);

void getArticleFail(String failMsg);

}

创建 ArticlePresenter

public class ArticlePresenter extends BasePresenter {

public void getArticleList(String key) {

}

}

上面我们说过,Presenter 层是由一个或多个 UseCase 组成,

他们的主要任务是执行异步任务,获取数据。那么我们在 domain 层定义一个 UseCase

名为 ArticleCase,详细代码如下:

public class ArticleCase extends UseCase<List, String> {

private ArticleRepository articleRepository;

public ArticleCase(ArticleRepository repository) {
this.articleRepository= repository;
}

@Override
protected Observable<List> buildObservable(String s) {
return articleRepository.getArticleList(s);
}

}

UseCase 是封装好的一个 Case 基类:

/**

  • Case 基类
  • @param 返回数据
  • @param 请求参数
    */
    public abstract class UseCase<T, Params> {

private final CompositeDisposable mDisposables;

public UseCase() {
this.mDisposables = new CompositeDisposable();
}

@SuppressLint(“CheckResult”)
public void execute(Params params, Consumer nextConsumer, Consumer errorConsumer) {
Observable observable = this.buildObservable(params);
addDisposable(observable.subscribe(nextConsumer, errorConsumer));
}

protected abstract Observable buildObservable(Params params);

private void addDisposable(Disposable disposable) {
mDisposables.add(disposable);
}

@SuppressLint(“CheckResult”)
public void execute(Params params, BaseObserver observer) {
Observable observable = this.buildObservable(params);
observable.subscribe(observer);
addDisposable(observer.getDisposable());
}

public void dispose() {
if (!mDisposables.isDisposed()) {
mDisposables.dispose();
}
}

}

任何一个业务类,都需要去继承 UseCase,并实现 buildObservable 方法。

继续看 ArticleCase,我们用到了接口 ArticleRepository,很明显,

这个接口用于被 data 层实现,从而获取数据并回调。

public interface ArticleRepository {

Observable<List> getArticleList(String param);

}

接下来在 data 层,去实现 ArticleRepository

public class ArticleRepositoryImpl implements ArticleRepository {

private DataApi mApi;

public ArticleRepositoryImpl() {
mApi = JDHttp.createApi(DataApi.class);
}

@Override
public Observable<List> getArticleList(String param) {
return mApi.getArticleList(param).compose(JDTransformer.switchSchedulers())
.map(new Function<BaseResponse, List>() {
@Override
public List apply(BaseResponse baseResponse) throws Exception {
return baseResponse.getResult().getList();
}
});
}
}

在这里,进行了获取数据操作。无论是从网络、还是本地获取,domain 层不需要知道。

然后在 Presenter 层中实现 ArticleCase,并调用 execute()方法,获取数据。

public class ArticlePresenter extends BasePresenter {

private ArticleCase mCase;​

public void getData(String key) {
mCase.execute(key, new BaseObserver<List>() {
@Override
public void onSuccess(List articleBeanList) {
getView().getArticleSuccess(articleBeanList);
}

@Override
public void onFail(String failMsg) {
getView().getArticleFail(failMsg);
}
});
}

@Override
public List createCases() {
mCase = new ArticleCase(new ArticleRepositoryImpl());
mCaseList.add(mCase);
return mCaseList;
}
}

并且在 BasePresenter 中实现自动取消订阅:

public abstract class BasePresenter implements IPresenter {

private V mView;

private CPBridge mBridge = new CPBridge();

protected List mCaseList = new ArrayList<>();

@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void attach(V view) {
this.mView = view;
createCases();
mCaseList.forEach(new Consumer() {
@Override
public void accept(UseCase useCase) {
mBridge.addCase(useCase);
}
});
}

@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void detach() {
this.mView = null;
mBridge.removeCase();
}

protected abstract List createCases();

public V getView() {
if (isViewAttached()) {
return mView;
} else {
throw new IllegalStateException(“Please call IPresenter.attach(IView view) before requesting data”);
}
}

private boolean isViewAttached() {
return null != mView;
}

}

感觉绕吗?没关系,结合简单的业务,将代码反复的敲几次,你就明白了,相信我。
具体代码实现请看 demo。
总结

通过上面的代码,实现一个业务,虽然写了好多类,好多代码。
但是这样写的好处也是显而易见的:整体架构更加清晰、易维护、方便测试、高内聚、低耦合。
同时也希望阅读过这篇文章的人,可以亲手实践。通过实践,你会明白很多之前不明白的问题。
希望这篇文章能对你有用,谢谢。
最后,附上 demo 地址:MVP-Clean-Demo
您的 star 是我前进的动力,欢迎 star!

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取
成体系的自学效果低效漫长且无助**。

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-AQfGPhjw-1719102816025)]一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值