新聞中心
前言

講道理,這次是真的筆者很久都沒有更新blog了,主要最近維護的框架問題也是層出不窮,而且對技術(shù)交流群的解答也讓我身心疲憊,所以在這里跟關(guān)注我的人說聲抱歉,沒有定期給你們帶來福利,那么這里就給大家?guī)硪粋€重磅福利:愛吖妹紙——Retrofit & RxJava & MVP & Butterknife 的完整App.
講到最近讓我身心疲憊的問題解答,無疑是讓我在開源的路上越走越遠,雖然我不是技術(shù)大牛,卻依然被一些很簡單的問題輪番轟炸,其實筆者的內(nèi)心真的是拒絕的。不得不說,寫給技術(shù)群內(nèi)的你和群主,為什么你提問,而總沒人回你!寫的挺好。
概述
廢話也不多說,對于MVP(Model View Presenter),我相信大多數(shù)人都能說出一些的,“MVC的演化版本”,“讓Model和View完全解耦”等等,但用過MVP的人一定會覺得,在Android中,代碼很清晰,不過多了很多類。對于大多數(shù)人而言,在看MVP的Demo的時候,一眼便是慢慢的nice,然而讓自己來寫個例子,卻很頭疼寫不出來。但的確MVC模式寫起來更加像是順水推舟。只需要把自己的業(yè)務(wù)邏輯一股腦的放進Activity就成功完事兒。
不得不說,之前我們項目中的確也是用的MVC在編寫的。很簡單的會發(fā)現(xiàn)隨便一個Activity代碼都是幾百上千行,甚至還有一萬行以上的??雌饋淼拇_那么一回事兒,但是細想這個View對于布局文件,其實能做的事情特別少,實際上關(guān)于該布局文件中的數(shù)據(jù)綁定的操作,事件處理的操作都在Activity中,造成了Activity既想View又像Controller,鄙棄代碼上的不美觀來說,對于后面的閱讀代碼真的是吃力。
不信?你瞧瞧。
也許業(yè)務(wù)邏輯比較簡單的功能用MVC沒什么,但是想沒想過,如果你產(chǎn)品后面改需求怎么辦?是的,你接受產(chǎn)品需求的強奸,但還是只有忍辱偷生。在日漸復(fù)雜的業(yè)務(wù)邏輯上,你的Activity和Fragment代碼越來越多,最終導(dǎo)致代碼爆炸,難以維護。
網(wǎng)上瀏覽一圈,發(fā)現(xiàn)講MVP的文章比比皆是,可見MVP的歡迎度,但大多數(shù)文章都只是講理論,稍微好點的會附帶一個簡單的登錄的Demo。然而,一個簡單的demo很難讓初次接觸MVP模式的人掌握它的使用。所以愛吖妹紙應(yīng)運而生。
什么是MVP
當然不能跑題,前面對 MVP 做了簡單的概述,下面還是用一個簡單的圖表示一下。
如上圖所示,在項目中 View 和 Model 并不直接交互,而是使用 Presenter 作為 View 和 Model 之間的橋梁。其中 Presenter 中同時持有 View 層以及 Model 層的 Interface 的引用,而 View 層持有 Presenter 層 Interface 的引用,當 View 層某個頁面需要展示某些數(shù)據(jù)的時候,首先會調(diào)用Presenter 層的某個接口,然后 Presenter 層會調(diào)用 Model 層請求數(shù)據(jù),當 Model 層數(shù)據(jù)加載成功之后會調(diào)用 Presenter 層的回調(diào)方法通知 Presenter 層數(shù)據(jù)加載完畢,*** Presenter 層再調(diào)用 View 層的接口將加載后的數(shù)據(jù)展示給用戶。這就是 MVP 模式的核心過程。
這樣分層的好處就是大大減少了Model與View層之間的耦合度。一方面可以使得View層和Model層單獨開發(fā)與測試,互不依賴。另一方面Model層可以封裝復(fù)用,可以極大的減少代碼量。當然,MVP還有其他的一些優(yōu)點,這里不再贅述。
功能展示
這里就給大家隨便看看干貨板塊的功能吧。
布局相當簡單。
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/swipe_refresh_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- android:id="@+id/recyclerView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
干貨模塊,也就是一個Fragment,里面有一個RecyclerView,支持下拉刷新和上拉加載數(shù)據(jù)。所以我們的 Presenter 和 View 只需要定義一下簡單的方法。
1)加載數(shù)據(jù)的過程中顯示加載的進度條;
2)加載數(shù)據(jù)成功提醒 Adapter 刷新數(shù)據(jù);
3)加載失敗談窗提醒用戶相關(guān)信息;
4)加載結(jié)束隱藏進度條;
- public interface CategoryContract {
- interface ICategoryView extends BaseView{
- void getCategoryItemsFail(String failMessage);
- void setCategoryItems(CategoryResult categoryResult);
- void addCategoryItems(CategoryResult categoryResult);
- void showSwipeLoading();
- void hideSwipeLoading();
- void setLoading();
- String getCategoryName();
- void noMore();
- } interface ICategoryPresenter extends BasePresenter{
- void getCategoryItems(boolean isRefresh);
- }
- }
編寫 Presenter 實現(xiàn)類。
- public class CategoryPresenter implements ICategoryPresenter {
- private ICategoryView mCategoryICategoryView;
- private int mPage = 1;
- private Subscription mSubscription;
- public CategoryPresenter(ICategoryView androidICategoryView) {
- mCategoryICategoryView = androidICategoryView;
- }
- @Override
- public void subscribe() {
- getCategoryItems(true);
- }
- @Override
- public void unSubscribe() {
- if (mSubscription != null && !mSubscription.isUnsubscribed()){
- mSubscription.unsubscribe();
- }
- } @Override
- public void getCategoryItems(final boolean isRefresh) {
- if (isRefresh) {
- mPage = 1;
- mCategoryICategoryView.showSwipeLoading();
- } else {
- mPage++;
- }
- mSubscription = NetWork.getGankApi()
- .getCategoryData(mCategoryICategoryView.getCategoryName(), GlobalConfig.CATEGORY_COUNT,mPage)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer
() { - @Override
- public void onCompleted() {
- }
- @Override
- public void onError(Throwable e) {
- mCategoryICategoryView.hideSwipeLoading();
- mCategoryICategoryView.getCategoryItemsFail(mCategoryICategoryView.getCategoryName()+" 列表數(shù)據(jù)獲取失?。?);
- }
- @Override
- public void onNext(CategoryResult categoryResult) {
- if (isRefresh){
- mCategoryICategoryView.setCategoryItems(categoryResult);
- mCategoryICategoryView.hideSwipeLoading();
- mCategoryICategoryView.setLoading();
- }else {
- mCategoryICategoryView.addCategoryItems(categoryResult);
- }
- }
- });
- }
- }
編寫Adapter,用于展示數(shù)據(jù)。
- class CategoryRecyclerAdapter extends CommonRecyclerAdapter
implements - ListenerWithPosition.OnClickWithPositionListener
{ - CategoryRecyclerAdapter(Context context) {
- super(context, null, R.layout.item_category);
- } @Override
- public void convert(CommonRecyclerHolder holder, ResultsBean resultsBean) {
- if (resultsBean != null) {
- ImageView imageView = holder.getView(R.id.category_item_img);
- if (ConfigManage.INSTANCE.isListShowImg()) { // 列表顯示圖片
- imageView.setVisibility(View.VISIBLE);
- String quality = "";
- if (resultsBean.images != null && resultsBean.images.size() > 0) {
- switch (ConfigManage.INSTANCE.getThumbnailQuality()) {
- case 0: // 原圖
- quality = "";
- break;
- case 1: //
- quality = "?imageView2/0/w/400";
- break;
- case 2:
- quality = "?imageView2/0/w/190";
- break;
- }
- Glide.with(mContext)
- .load(resultsBean.images.get(0) + quality)
- .placeholder(R.mipmap.image_default)
- .error(R.mipmap.image_default)
- .into(imageView);
- } else { // 列表不顯示圖片
- Glide.with(mContext).load(R.mipmap.image_default).into(imageView);
- }
- } else {
- imageView.setVisibility(View.GONE);
- }
- holder.setTextViewText(R.id.category_item_desc, resultsBean.desc == null ? "unknown" : resultsBean.desc);
- holder.setTextViewText(R.id.category_item_author, resultsBean.who == null ? "unknown" : resultsBean.who);
- holder.setTextViewText(R.id.category_item_time, TimeUtil.dateFormat(resultsBean.publishedAt));
- holder.setTextViewText(R.id.category_item_src, resultsBean.source == null ? "unknown" : resultsBean.source);
- holder.setOnClickListener(this, R.id.category_item_layout);
- }
- } @Override
- public void onClick(View v, int position, CommonRecyclerHolder holder) {
- &n
本文標題:淺淡MVP的實戰(zhàn)演習,讓代碼結(jié)構(gòu)更簡單~
標題來源:http://www.5511xx.com/article/ccshshd.html


咨詢
建站咨詢
