1. 程式人生 > >Android MVP系列(四)之完整MVC

Android MVP系列(四)之完整MVC

今天這篇文章主要分為兩大部分

一、為上一章的MVC賦予靈動的生命
二、指出MVC的不足和引出MVP的優點

題外話

可能有人會說,你寫個MVP,為啥用了前面三篇(Android MVP系列(一)、Android MVP系列(二)之MVC結構、Android MVP系列(三)之MVC中篇)加上本篇來敘述MVC,我花這麼幾個章節來詳細解釋MVC,就是為了讓我們能更加容易理解、掌握MVP的框架,通過MVC來平滑過渡到MVP,讓讀者能更加的自然的接受,不至於突兀,有點不知所措。如果還沒有閱讀過之前章節的同學,不妨花點時間耐心看看之前的章節,MVC和MVP是有很多共性的。

第一部分:為MVC賦予靈動的生命

溝通機制

上一章我們最後搭建了一個MVC框架的雛形,但是在文末的時候我提出說:這個框架看起來比較死板、靈活性不強,感覺哪裡怪怪的,缺少點生命靈性。
這就是我這個章節要重點講解的:溝通機制。看上一章我們搭建的框架,沒有哪個地方有溝通機制,所以看起來比較死板。
JAVA裡面有一種設計模式叫觀察者模式,那麼這裡就是我要說的溝通機制;如果不清楚的也沒關係,我會一步一步的講解。

觀察者模式也叫:釋出-訂閱模式。

觀察者模式的主要兩個人物:
Observer(觀察者)、Obserable(被觀察者)

整個事件的驅動過程:
訂閱(Subcribe)、傳送事件、接收事件、處理事件

那我們已經清楚觀察者模式的基本結構,那麼我們將觀察者模式應用到我們的MVC框架中,讓框架賦予靈性。

場景

在之前的MVC框架上,我們增加需求:

給列表增加重新整理功能

MVC框架新增監聽機制滿足功能需求

第一步、建立觀察者

       首先我們想想需求,我們是要重新整理列表,我們需要觀察者觀察什麼呢?這個需求當中最主要的就是重新整理資料,也就是說最重要的就是資料是否重新整理完成是一個點,這個點就是我們要觀察的目標。所以我們的觀察者就需要具備資料是否重新整理完成的能力

按照上面的推理步驟我們可以寫出一個觀察者介面:

/**我是一個“觀察者”**/
public interface
Observer {
/**監聽資料重新整理完成**/ void onRefreshFinish(List<NewsBean> data); }

這就是我們的觀察者了,但是我們還沒寫到MVC框架裡面讓誰有這個觀察者能力呢?這裡我們就需要明白MVC框架的分層理解了,回顧一下:

Module層職責

Module層資料模型層,對業務邏輯的處理,資料庫、網路、演算法等。

View層職責

1.呈現M層的資料
2.主動詢問或者被動監聽(例如:下拉重新整理列表主動詢問)
3.通知C層處理
4.接收C層,改變UI

Controller層職責

接收V層的操控,並轉調給M層來改變V層UI或者狀態

按照功能來區分的話,我們看得出只有Controller層最合適,由於它主要是接收View的控制,轉調Module去伺服器重新整理資料,再來改變View重新整理列表。

因此我們賦予Controller觀察者的能力:

/**我是一個Contorller,同時我就是觀察者**/
public class Controller implements Observer{
 /**接收事件**/
 @Override
 void  onRefreshFinish(List<NewsBean> data){
  //處理事件
 }
  ...
  ...
  ...
}

第二步、建立被觀察者、並訂閱

這裡毫無疑問就是Module層是被觀察者,Module去訂閱

/**這是一個Model**/
public class Module{
private IView view;
private Observer observer;

//構造方法傳入View
public void Module(IView view){
this.view=view;
}
//訂閱觀察者
public void addObserver(Observer observer){
this.observer=observer;
}
//從伺服器請求獲取新聞列表資料
void getNewsData(boolean flag) {
//耗時獲取資料
...
//將伺服器返回的List<NewsBean>集合dataList儲存到本地
this.saveCacheNews(dataList,flag);
}
//儲存新聞列表到記憶體中
void saveCacheNews(Lis<NewsBean> dataList,boolean flag){
//儲存到本地
...
//判斷下重新整理還是初始化
if(flag){
 //傳送事件
 observer.onRefreshFinish(dataList);
 }else{
  //通知view 重新整理列表了
  view.updateView();
 }

}
//從記憶體快取獲取資料
NewsBean getNewsCache() {
//記憶體中去獲取資料 datas
...
return datas;
}
}

第三步、訂閱者接收事件

/**這是一個Contorller**/
public class Controller implements Observer{
private IView view;
private Module module;
//構造方法注入View
public void Controller(IView view){
this.view=view;
}
//注入Module
public void Controller(Module module){
this.module=module;
}
//轉調Module載入資料
void loadNewsList(boolean flag) {
//做個判斷是重新整理還是初始化
 if(flag){
   module.getNewsData(false);
   view.showLoading();
 }else{
   if(module.getNewsCache() == null){
     //執行Modle
     module.getNewsData(false);
     //執行View開始載入資料了,顯示載入動畫
     view.showLoading();
    }
  }
}
 /**接收事件**/
 @Override
 public void onRefreshFinish(List<NewsBean> datas){
  //處理事件 onDataBack哪兒來的,我們處理view的時候說明
  view.onDataBack(datas);
 }
}

最後一步,我們View中怎麼處理事件的呢?
我們現在的框架算是比較完整了,

public class MainActivity extends AppCompatActivity implments IView{
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化Controller,this就是View,通過構造器注入
Controller controller = new Controller(this);

//初始化Model,Model -> View and View -> Model
Module model = new Module(this);
//module注入到Controller
controller.setModule(module);
//Controller -> Model  這個地方就是我們的訂閱事件了  controller是Observer的實現類
model.addObserver(controller);
//初始化,讓Controller轉調Module請求資料
this.viewInit(false);
}
@Override
public void updateView(){
//主動請求Model獲取資料
NewsBean data = module.getNewsCache();
//更新ui
list.update(data);
//隱藏loading介面
this.hideLoading()
}
@Override
public void showLoading(){
list.showLoading()
}
@Override
public void hideLoading(){
list.hideLoading
}
//重新整理介面資料了,通知Controller
//flag 表示判斷是初始化介面還是重新整理資料 false 初始化 true 重新整理
public void viewInit(boolean flag){
controller.loadNewsList(flag);
}
//相當於我們的下拉重新整理列表的時候,activity中呼叫onRefresh方法
pulic void onRefresh(){
 controller.loadNewsList(true);
}
 //Controller層接收事件之後,控制View處理事件,重新整理介面
 public void onDataBack(List<NewsBean> datas){
 list.update(datas);
 this.hideLoading
 }

}

這樣我們的MVC的框架就算是比較完整了;

View層:觸發重新整理、接收資料、更新UI介面,資料怎麼來的一概不管。
Contronller層:接收View控制、轉調Module層請求資料、控制View的狀態、監聽重新整理資料完成。
Module層:處理資料、請求資料。

各個層的職責非常清楚、便於維護、邏輯清晰等優點。

總結

       在MVC這個模式中,我們建立的溝通機制,是最常見的方式。但是我們很多人一眼看的出來,在View層中既有Module物件,又有Controller物件,Controller層中也有Module物件,Module層中又含有Controller物件,這樣複雜的物件引用關係,估計很多人都暈了。
       而且這種複雜的引用關係,不利於管理,可擴充套件性也差,所以這才有了我們MVP的框架,MVP有兩個非常重要的能力:複用性和可擴充套件性,還有就是解決物件的複雜引用關係、便於維護。

第二部分引出MVP

新的場景

我們都是上班族,畢竟面臨租房子的問題,那麼我們經常租房子肯定是找中介。現在我們就有三個人物:租客、中介、房東三個人物

這裡寫圖片描述

這個圖和我們的MVC的圖片貌似神似啊(原諒我畫的有點醜),但是這個場景就和我們的MVC非常符合,但是現在新的需求改變了:

由於房東比較忙,他給中介說,我比較忙我不想和租客去溝通價格、修理傢俱。。。等等很多的事情,你都給我辦了,包括租金,租約你都處理了,我就收錢就好了,其他的我不管。現在的圖形就演變成下面這樣了:
這裡寫圖片描述
當然這個圖裡面付錢,籤合同等都是中介完成,就沒有畫出來了,但是我們可以清楚的看到房東和租客沒有任何聯絡了,一切事情找中介就好了。那麼這張圖和我們的MVP的經典圖片又有什麼區別呢?
這裡寫圖片描述
這種模式下人員關係方面簡單得多,這裡我們把:

租客==View、中介==Presenter、房東==Module

       現在的關係非常清楚,租客(View)只和中介(Presenter)聯絡,房東(Module)也只和中介聯絡(Presenter);假如中介換人了,按照之前的結構不需要任何改變,複用性強;現在房東只管收錢就好了,其他的事情都由中介處理,租客交租金、修電器、出現的等等問題,直接和中介溝通解決,等於可擴充套件性也強,最終知會一下房東就好。不知道這樣解釋清不清楚,假設如果還是理解不清楚,沒關係,下一章節我們用程式碼的形式展示就會很清楚了

那就期待一下章節的從MVC平滑過渡到MVP,讓你輕鬆掌握MVP。

原創不易,如果覺得寫得好,掃碼關注一下點個贊,是我最大的動力。

關注我,一定會有意想不到的東西等著你:
每天專注分享Android、JAVA乾貨
這裡寫圖片描述

備註:程式圈LT
微信掃一掃
關注該公眾號

相關推薦

Android MVP系列完整MVC

今天這篇文章主要分為兩大部分: 一、為上一章的MVC賦予靈動的生命; 二、指出MVC的不足和引出MVP的優點; 題外話 可能有人會說,你寫個MVP,為啥用了前面三篇(Android MVP系列(一)、Android MVP系列(二)之MVC結構、Andr

Spring MVC系列session處理[email

介紹        在web開發中,session的重要性不言而喻,與cookie相比,session更加安全,處於伺服器端,開發者經常把一些重要的資訊放在session,方便在多次請求中方便的獲取資訊,Spring MVC 對session的支援也依舊很強大很靈活 Sp

Android學習筆記碎片化Fragment實現仿人人客戶端的側邊欄

    其實一種好的UI佈局,可以使使用者感到更加的親切與方便。最近非常流行的莫過於側邊欄了,其實我也做過很多側邊欄的應用,但是那些側邊欄的使用我都不是很滿意,現在重新整理,重新寫了一個相對來說我比較滿意的側邊欄,其中運用的就是android3.0版本之後新加的Fragme

深度學習基礎系列 sklearn SVM

1、背景 1.1 最早是由 Vladimir N. Vapnik 和 Alexey Ya. Chervonenkis 在1963年提出 1.2 目前的版本(soft margin)是由Corinna Cortes 和 Vapnik在1993年提出,並在199

物聯網平臺構架系列 :Amazon, Microsoft, IBM IoT 平臺導論 平臺

物聯網; iot; aws; 亞馬遜; greengrass;microsoft; azure;ibm; watson; bluemix最近研究了一些物聯網平臺技術資料,以做選型參考。腦子裏積累大量信息,便想寫出來做一些普及。作為科普文章,力爭通俗易懂,不確保概念嚴謹性。我會給考據癖者提供相關英文鏈接,以便深

【原創】源碼角度分析Android的消息機制系列——MessageQueue的工作原理

enc 容易 工作 trie oss 當前 within which ptime ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 MessageQueue,主要包含2個操作:插入和讀取。讀取操作會伴隨著刪除操作,插入和讀取對應的方法分別為enqueueMes

Python爬蟲系列:Beautiful Soup解析HTML把HTML轉成Python對象

調用 nor 結束 版本 現在 name屬性 data 官方文檔 get 在前幾篇文章,我們學會了如何獲取html文檔內容,就是從url下載網頁。今天開始,我們將討論如何將html轉成python對象,用python代碼對文檔進行分析。 (牛小妹在學校折騰了好幾天,也沒把h

spring-boot-2.0.3不一樣系列源碼篇 - run方法prepareContext,絕對有值得你看的地方

release led 設置 get handler htm encoding 列表創建 splay 前言   此系列是針對springboot的啟動,旨在於和大家一起來看看springboot啟動的過程中到底做了一些什麽事。如果大家對springboot的源碼有所研究,可

床頭筆記Android開發學習

新建HelloWorld工程專案目錄說明: 工程目錄: 按著下圖順序講解 HelloWorld: 專案名 src: 自己編寫的程式存放處 gen: 系統自動生成的檔案R.java(和res資原始檔關聯,為其子檔案drawable下每個圖片及values下的鍵值

程式設計師網路安全系列:資料加密非對稱祕鑰

系列目錄: 前文回顧 假如,明明和麗麗相互不認識,明明想給麗麗寫一封情書,讓隔壁老王送去 如何保證隔壁老王不能看到情書內容?(保密性) 如何保證隔壁老王不修改情書的內容?(完整性) 如何保證隔壁老王不冒充明明?(身份認證) 如何保證明明不能否認情書是自己寫的?(來源的不可否認) 但是上面的問題是明

Android簡易計算器—— 完整邏輯程式碼

  最近在學安卓的相關知識,第一個demo做了一個簡易計算器,功能仿手機上自帶的計算器,沒有加括號,簡單的四則運算,支援長表示式運算。此篇貼出本次簡易計算器完整邏輯程式碼。 程式碼如下: package com.example.zwkkkk1.cacul

Android外掛化學習使用外掛中的R資源

res裡的每一個資源都會在R.java裡生成一個對應的Integer型別的id,APP啟動時會先把R.java註冊到當前的上下文環境,我們在程式碼裡以R檔案的方式使用資源時正是通過使用這些id訪問res資源,然而外掛的R.java並沒有註冊到當前的上下文環境,所

資料探勘入門系列教程基於scikit-lean實現決策樹

資料探勘入門系列教程(四)之基於scikit-lean決策樹處理Iris載入資料集資料特徵訓練隨機森林調參工程師結尾 資料探勘入門系列教程(四)之基於scikit-lean決策樹處理Iris 在上一篇部落格,我們介紹了決策樹的一些知識。如果對決策樹還不是很瞭解的話,建議先閱讀上一篇部落格,在來學習這

bfzwjeqjSpriNgMc學習系列3url

ref htm 學習 pri blank url lan get 系列 bfzwjeqjSpriNgMc學習系列(3)之url χ絳 bfzwjeqjSpriNgMc學習系列(3)之urlbfzwjeqjSpriNgMc學習系列(3)之url

elasticsearch系列部署

linux .tar.gz ast 官方 hup bin arc 分享 quest linux環境 centOS6.8 本文采用tar包的方式部署es 準備jdk8的環境 5.4.0的es依賴jdk8及以上版本 下載linux版的jdk jdk-8u121-linux-x6

搜索引擎ElasticSearch系列: ElasticSearch2.4.4 sql插件安裝

china code als 插件 技術分享 -s fun nlp 4.0 一:ElasticSearch sql插件簡介   With this plugin you can query elasticsearch using familiar SQL syntax.

mysql基礎索引

name 根據 正是 而不是 方案 加速 .com mtab 技術 索引簡介: 1、普通索引   普通索引(由關鍵字KEY或INDEX定義的索引)的唯一任務是加快對數據的訪問速度。因此,應該只為那些最經常出現在查詢條件 (WHEREcolumn=)或排序條件

源碼分析系列x264_nal_dataflow

以及 生成 taf inf enc logs can data 碼率 http://www.cnblogs.com/xkfz007/articles/2616158.html NAL部分關鍵函數 4.1 int x264_nal_encode( void *, int

從零開始搭建android框架系列

bsp andro hup 開始 blank class and lan com 網址:從零開始搭建android框架系列 githup:https://github.com/CameloeAnthony/Ant從零開始搭建android框架系列(轉)

Andrew Ng機器學習課程筆記神經網絡

sca 優化 介紹 www 之間 output 現在 利用 href Andrew Ng機器學習課程筆記(四)之神經網絡 版權聲明:本文為博主原創文章,轉載請指明轉載地址 http://www.cnblogs.com/fydeblog/p/7365730.html 前言